Introduction

In this project, we basically analyze how STEM policy influences the whole American Society, including the citizens and the non-citizens. To make the topic more revelent to ourselves, our analysis contains two main parts: (1) how STEM policy influences graduated students, and (2) how STEM policy influences employment situation.

In part (1), we use several data sets to understand how STEM degrees develop into STEM jobs. In part (2), we use data sets from 2007 and 2014 to compare the employment situations and working conditions before and after the announcement of the STEM policy.

Team member: Yaqing Xie Qing Yin Yueqi Zhang

Part 1. Influences of STEM policy on graduated students

1. Our Objective

In this part of analysis, we want to know how STEM policy influence graduated students. We first separate our data into 2 categories: one category includes citizens and the other category includes non-citizens. Then, we further separate our data into STEM-major data and non-STEM-major data. By doing the separations, we can easily do comparisons between influences of STEM policy to citizens and influences of STEM policy to non-citizens and between employment status of STEM majors and employment status of non-STEM majors.

2. Our Concerns

  1. Is it true that graduated students with STEM degrees can easily find jobs?

  2. Do levels of degrees influence employment rate of STEM students? Do levels of degrees influence employment rate of non-STEM students?

  3. Which fields will STEM graduated students enter and which fields will non-STEM graduated students enter?

3. Our Findings

Before we start to analyze data, we should clean and preprocess data. For example, we categorize people according to their degree field as stem or non-stem.

library(data.table)
library(dplyr)
cols<-c("SERIALNO","SPORDER","ST","AGEP","CIT","NWLK","SCH","SCHL","WKL","WRK","FOD1P","OCCP")
data14a<-fread("/Users/YaqingXie/Desktop/Applied Data Science/Week1/csv_pus/ss14pusa.csv",select=cols)
data14b<-fread("/Users/YaqingXie/Desktop/Applied Data Science/Week1/csv_pus/ss14pusb.csv",select=cols)
data14<-rbind(data14a,data14b)
data14<-filter(data14,FOD1P!="NA")
stem<-matrix(rep(0,dim(data14)[1]),nrow=dim(data14)[1])
stem.field<-c(1103,1104,1105,1106,1301,1401,2100,2101,2102,2105,2106,2107,2400,2401,2402,2403,2404,2407,2408,2409,2410,2411,2412,2413,2414,2415,2416,2417,2418,2419,2499,2500,2501,2502,2503,2504,2599,3600,3601,3602,3603,3604,3605,3606,3607,3608,3609,3611,3699,3700,3701,3702,3801,4002,4005,4006,5000,5001,5002,5003,5004,5005,5006,5007,5008,5102,5206,5901,6105,6202,6212)
l<-length(stem.field)
order.fod<-c()
for(i in 1:l)
{
  order.fod<-c(order.fod,which(data14$FOD1P==stem.field[i]))
}
order.fod<-sort(order.fod)
stem[order.fod]<-1
colnames(stem)<-"STEM"
data14<-cbind(data14,stem)
data14$CIT[which(data14$CIT==5)]<-0
data14$CIT[which(data14$CIT==4)]<-1
data14$CIT[which(data14$CIT==3)]<-1
data14$CIT[which(data14$CIT==2)]<-1
data14<-subset(data14,data14$SCH==1)
data14<-filter(data14,data14$SCHL>20)
data14$OCCP[which(data14$NWLK==1)]<-"NA"
data14$OCCP[which(data14$WKL==2)]<-"NA"
data14$OCCP[which(data14$WRK==2)]<-"NA"
data14$OCCP[which(data14$OCCP==9920)]<-"NA"
occp.type<-matrix(rep(0,dim(data14)[1]),nrow=dim(data14)[1])
occp.mgr<-c(0010,0020,0040,0050,0060,0100,0120,0135,0136,0137,0140,0150,0160,0205,0220,0230,0300,0310,0330,0340,0350,0360,0410,0420,0425,0430)
for(i in 1:length(occp.mgr))
{
  occp.type[which(data14$OCCP==occp.mgr[i])]<-"MGR"
}
occp.bus<-c(0500,0510,0520,0530,0540,0565,0600,0630,0640,0650,0700,0710,0725,0726,0735,0740)
for(i in 1:length(occp.bus))
{
  occp.type[which(data14$OCCP==occp.bus[i])]<-"BUS"
}
occp.fin<-c(0800,0810,0820,0830,0840,0850,0860,0900,0910,0930,0940,0950)
for(i in 1:length(occp.fin))
{
  occp.type[which(data14$OCCP==occp.fin[i])]<-"FIN"
}
occp.cmm<-c(1005,1006,1007,1010,1020,1030,1050,1060,1105,1106,1107,1200,1220,1240)
for(i in 1:length(occp.cmm))
{
  occp.type[which(data14$OCCP==occp.cmm[i])]<-"CMM"
}
occp.eng<-c(1300,1310,1320,1340,1350,1360,1400,1410,1420,1430,1440,1450,1460,1520,1530,1540,1550,1560)
for(i in 1:length(occp.eng))
{
  occp.type[which(data14$OCCP==occp.eng[i])]<-"ENG"
}
occp.sci<-c(1600,1610,1640,1650,1700,1710,1720,1740,1760,1800,1820,1840,1860,1900,1910,1920,1930,1965)
for(i in 1:length(occp.sci))
{
  occp.type[which(data14$OCCP==occp.sci[i])]<-"SCI"
}
occp.cms<-c(2000,2010,2015,2016,2025,2040,2050,2060)
for(i in 1:length(occp.cms))
{
  occp.type[which(data14$OCCP==occp.cms[i])]<-"CMS"
}
occp.lgl<-c(2100,2105,2145,2160)
for(i in 1:length(occp.lgl))
{
  occp.type[which(data14$OCCP==occp.lgl[i])]<-"LGL"
}
occp.edu<-c(2200,2300,2310,2320,2330,2340,2440,2540,2550)
for(i in 1:length(occp.edu))
{
  occp.type[which(data14$OCCP==occp.edu[i])]<-"EDU"
}
occp.ent<-c(2600,2630,2700,2710,2720,2740,2750,2760,2800,2810,2825,2830,2840,2850,2860,2900,2910,2920)
for(i in 1:length(occp.ent))
{
  occp.type[which(data14$OCCP==occp.ent[i])]<-"ENT"
}
occp.med<-c(3000,3010,3030,3040,3050,3060,3110,3120,3140,3150,3160,3200,3210,3220,3230,3245,3250,3255,3256,3258,3260,3300,3310,3320,3400,3420,3500,3510,3520,3535,3540)
for(i in 1:length(occp.med))
{
  occp.type[which(data14$OCCP==occp.med[i])]<-"MED"
}
occp.hls<-c(3600,3610,3620,3630,3640,3645,3646,3647,3648,3649,3655)
for(i in 1:length(occp.hls))
{
  occp.type[which(data14$OCCP==occp.hls[i])]<-"HLS"
}
occp.prt<-c(3700,3710,3720,3730,3740,3750,3800,3820,3840,3850,3900,3910,3930,3940,3945,3955)
for(i in 1:length(occp.prt))
{
  occp.type[which(data14$OCCP==occp.prt[i])]<-"PRT"
}
occp.eat<-c(4000,4010,4020,4030,4040,4050,4060,4110,4120,4130,4140,4150)
for(i in 1:length(occp.eat))
{
  occp.type[which(data14$OCCP==occp.eat[i])]<-"EAT"
}
occp.cln<-c(4200,4210,4220,4230,4240,4250)
for(i in 1:length(occp.cln))
{
  occp.type[which(data14$OCCP==occp.cln[i])]<-"CLN"
}
occp.prs<-c(4300,4320,4340,4350,4400,4410,4420,4430,4460,4465,4500,4510,4520,4530,4540,4600,4610,4620,4640,4650)
for(i in 1:length(occp.prs))
{
  occp.type[which(data14$OCCP==occp.prs[i])]<-"PRS"
}
occp.sal<-c(4700,4710,4720,4740,4750,4760,4800,4810,4820,4830,4840,4850,4900,4920,4930,4940,4950,4965)
for(i in 1:length(occp.sal))
{
  occp.type[which(data14$OCCP==occp.sal[i])]<-"SAL"
}
occp.off<-c(5000,5010,5020,5030,5100,5110,5120,5130,5140,5150,5160,5165,5200,5220,5230,5240,5250,5260,5300,5310,5320,5330,5340,5350,5360,5400,5410,5420,5500,5510,5520,5530,5540,5550,5560,5600,5610,5620,5630,5700,5800,5810,5820,5840,5850,5860,5900,5910,5920,5940)
for(i in 1:length(occp.off))
{
  occp.type[which(data14$OCCP==occp.off[i])]<-"OFF"
}
occp.fff<-c(6005,6010,6040,6050,6100,6120,6130)
for(i in 1:length(occp.fff))
{
  occp.type[which(data14$OCCP==occp.fff[i])]<-"FFF"
}
occp.con<-c(6200,6210,6220,6230,6240,6250,6260,6300,6320,6330,6355,6360,6400,6420,6440,6460,6515,6520,6530,6600,6660,6700,6710,6720,6730,6740,6765)
for(i in 1:length(occp.con))
{
  occp.type[which(data14$OCCP==occp.con[i])]<-"CON"
}
occp.ext<-c(6800,6820,6830,6840,6940)
for(i in 1:length(occp.ext))
{
  occp.type[which(data14$OCCP==occp.ext[i])]<-"EXT"
}
occp.rpr<-c(7000,7010,7020,7030,7040,7100,7110,7120,7130,7140,7150,7160,7200,7210,7220,7240,7260,7300,7315,7320,7330,7340,7350,7360,7410,7420,7430,7510,7540,7560,7610,7630)
for(i in 1:length(occp.rpr))
{
  occp.type[which(data14$OCCP==occp.rpr[i])]<-"RPR"
}
occp.prd<-c(7700,7710,7720,7730,7740,7750,7800,7810,7830,7840,7850,7855,7900,7920,7930,7940,7950,8030,8040,8100,8130,8140,8220,8250,8255,8256,8300,8310,8320,8330,8350,8400,8410,8420,8450,8460,8500,8510,8530,8540,8550,8600,8610,8620,8630,8640,8650,8710,8720,8730,8740,8750,8760,8800,8810,8830,8850,8910,8920,8930,8940,8950,8965)
for(i in 1:length(occp.prd))
{
  occp.type[which(data14$OCCP==occp.prd[i])]<-"PRD"
}
occp.trn<-c(9000,9030,9040,9050,9110,9120,9130,9140,9150,9200,9240,9260,9300,9310,9350,9360,9410,9415,9420,9510,9520,9560,9600,9610,9620,9630,9640,9650,9720,9750)
for(i in 1:length(occp.trn))
{
  occp.type[which(data14$OCCP==occp.trn[i])]<-"TRN"
}
occp.mil<-c(9800,9810,9820,9830,9920)
for(i in 1:length(occp.mil))
{
  occp.type[which(data14$OCCP==occp.mil[i])]<-"MIL"
}
colnames(occp.type)<-"OCCP.TYPE"
data14<-cbind(data14,occp.type)
write.csv(data14,file="data2014.csv",row.names = FALSE)
data.14<-fread("data2014.csv",select=c("ST","AGEP","CIT","SCHL","FOD1P","OCCP","STEM","OCCP.TYPE"))
write.csv(data.14,file="fndata2014.csv",row.names = FALSE)

data.14.noncit<-subset(data.14,data.14$CIT==0)
data.14.cit<-subset(data.14,data.14$CIT!=0)
write.csv(data.14.cit,file="data2014_cit.csv",row.names=FALSE)
write.csv(data.14.noncit,file="data2014_noncit.csv",row.names=FALSE)

We also separate data into two parts according to people’s citizenship status.

setwd("/Users/YaqingXie/Desktop/Applied Data Science/Fall2016-proj1-grp15/data")
pus11<-read.csv("fndata2011.csv")
pus12<-read.csv("fndata2012.csv")
pus13<-read.csv("fndata2013.csv")
pus14<-read.csv("fndata2014.csv")

pus11cit<-pus11[pus11$CIT==1,]
pus11ncit<-pus11[pus11$CIT==0,]
pus12cit<-pus12[pus12$CIT==1,]
pus12ncit<-pus12[pus12$CIT==0,]
pus13cit<-pus13[pus13$CIT==1,]
pus13ncit<-pus13[pus13$CIT==0,]
pus14cit<-pus14[pus14$CIT==1,]
pus14ncit<-pus14[pus14$CIT==0,]

Below shows the structure of our processed data.

library(DT)
datatable(head(pus11cit,50),options=list(scrollX=T,pageLength=10))

(1) Rate of Employment

The first plot we obtained explains how the rate of employment varies among citizens or non-citizens with stem or non-stem degree.

# In this part, I am going to check the 4-year employment rates in each category.
# First, I will eliminate the rows with age greater than or equal to 66.
pus11citstemy<-pus11cit[pus11cit$STEM==1&pus11cit$AGEP<66,]
pus11citnstemy<-pus11cit[pus11cit$STEM==0&pus11cit$AGEP<66,]
pus11ncitstemy<-pus11ncit[pus11ncit$STEM==1&pus11ncit$AGEP<66,]
pus11ncitnstemy<-pus11ncit[pus11ncit$STEM==0&pus11ncit$AGEP<66,]
pus12citstemy<-pus12cit[pus12cit$STEM==1&pus12cit$AGEP<66,]
pus12citnstemy<-pus12cit[pus12cit$STEM==0&pus12cit$AGEP<66,]
pus12ncitstemy<-pus12ncit[pus12ncit$STEM==1&pus12ncit$AGEP<66,]
pus12ncitnstemy<-pus12ncit[pus12ncit$STEM==0&pus12ncit$AGEP<66,]
pus13citstemy<-pus13cit[pus13cit$STEM==1&pus13cit$AGEP<66,]
pus13citnstemy<-pus13cit[pus13cit$STEM==0&pus13cit$AGEP<66,]
pus13ncitstemy<-pus13ncit[pus13ncit$STEM==1&pus13ncit$AGEP<66,]
pus13ncitnstemy<-pus13ncit[pus13ncit$STEM==0&pus13ncit$AGEP<66,]
pus14citstemy<-pus14cit[pus14cit$STEM==1&pus14cit$AGEP<66,]
pus14citnstemy<-pus14cit[pus14cit$STEM==0&pus14cit$AGEP<66,]
pus14ncitstemy<-pus14ncit[pus14ncit$STEM==1&pus14ncit$AGEP<66,]
pus14ncitnstemy<-pus14ncit[pus14ncit$STEM==0&pus14ncit$AGEP<66,]
# Then, I will calculate the 4-year employment rates in each category.
citstememp<-c(nrow(pus11citstemy[!is.na(pus11citstemy$OCCP),])/nrow(pus11citstemy),nrow(pus12citstemy[!is.na(pus12citstemy$OCCP),])/nrow(pus12citstemy),nrow(pus13citstemy[!is.na(pus13citstemy$OCCP),])/nrow(pus13citstemy),nrow(pus14citstemy[!is.na(pus14citstemy$OCCP),])/nrow(pus14citstemy))
citnstememp<-c(nrow(pus11citnstemy[!is.na(pus11citnstemy$OCCP),])/nrow(pus11citnstemy),nrow(pus12citnstemy[!is.na(pus12citnstemy$OCCP),])/nrow(pus12citnstemy),nrow(pus13citnstemy[!is.na(pus13citnstemy$OCCP),])/nrow(pus13citnstemy),nrow(pus14citnstemy[!is.na(pus14citnstemy$OCCP),])/nrow(pus14citnstemy))
ncitstememp<-c(nrow(pus11ncitstemy[!is.na(pus11ncitstemy$OCCP),])/nrow(pus11ncitstemy),nrow(pus12ncitstemy[!is.na(pus12ncitstemy$OCCP),])/nrow(pus12ncitstemy),nrow(pus13ncitstemy[!is.na(pus13ncitstemy$OCCP),])/nrow(pus13ncitstemy),nrow(pus14ncitstemy[!is.na(pus14ncitstemy$OCCP),])/nrow(pus14ncitstemy))
ncitnstememp<-c(nrow(pus11ncitnstemy[!is.na(pus11ncitnstemy$OCCP),])/nrow(pus11ncitnstemy),nrow(pus12ncitnstemy[!is.na(pus12ncitnstemy$OCCP),])/nrow(pus12ncitnstemy),nrow(pus13ncitnstemy[!is.na(pus13ncitnstemy$OCCP),])/nrow(pus13ncitnstemy),nrow(pus14ncitnstemy[!is.na(pus14ncitnstemy$OCCP),])/nrow(pus14ncitnstemy))
# Finally, I will visualize the 4-year employment rates in each category.
empmat<-rbind(citstememp,citnstememp,ncitstememp,ncitnstememp)
colnames(empmat)<-c("2011","2012","2013","2014")
rownames(empmat)<-c("citizen STEM","citizen non-STEM","non-citizen STEM","non-citizen non-STEM")
empdf<-data.frame(year=factor(rep(c("2011","2012","2013","2014"),each=4),levels=c("2011","2012","2013","2014")),status=factor(rep(c("citizen STEM","citizen non-STEM","non-citizen STEM","non-citizen non-STEM"),4)),rate=c(empmat[,1],empmat[,2],empmat[,3],empmat[,4]))
library(ggplot2)
ggplot(data=empdf,aes(x=year,y=rate,fill=status))+geom_bar(stat="identity",position=position_dodge())+geom_text(aes(label=round(rate,2)),position=position_dodge(width=0.9)) + ggtitle("Employment Rate of Different Degree/Citizenship Type v.s. Time") + theme(plot.title = element_text(size = rel(1),face="bold"))

From the plot we can see that the rate is quite stable at least in recent years, and in general Citizens other than non-citizens, STEM degrees other than non-STEM degrees are more favorable in employers’ eye.

Now we start to think how advanced degree influences the employment rate. From the following figure, we see how important it is for non-citizens to get a higher degree, since for citizens with either STEM or non-STEM degree, the rate stays somewhat stable among different degree groups, while for non-citizens, the rate can change significantly.

# In this part, I am going to calculate employment rates of different degrees in each category. The data set that I use here is the 2014 data set.
# First, I should further separate the data sets using the variable SCHL (degree level).
pus14citstemyb<-pus14citstemy[pus14citstemy$SCHL==21,]
pus14citstemym<-pus14citstemy[pus14citstemy$SCHL==22,]
pus14citstemyp<-pus14citstemy[pus14citstemy$SCHL==23,]
pus14citstemyd<-pus14citstemy[pus14citstemy$SCHL==24,]
pus14citnstemyb<-pus14citnstemy[pus14citnstemy$SCHL==21,]
pus14citnstemym<-pus14citnstemy[pus14citnstemy$SCHL==22,]
pus14citnstemyp<-pus14citnstemy[pus14citnstemy$SCHL==23,]
pus14citnstemyd<-pus14citnstemy[pus14citnstemy$SCHL==24,]
pus14ncitstemyb<-pus14ncitstemy[pus14ncitstemy$SCHL==21,]
pus14ncitstemym<-pus14ncitstemy[pus14ncitstemy$SCHL==22,]
pus14ncitstemyp<-pus14ncitstemy[pus14ncitstemy$SCHL==23,]
pus14ncitstemyd<-pus14ncitstemy[pus14ncitstemy$SCHL==24,]
pus14ncitnstemyb<-pus14ncitnstemy[pus14ncitnstemy$SCHL==21,]
pus14ncitnstemym<-pus14ncitnstemy[pus14ncitnstemy$SCHL==22,]
pus14ncitnstemyp<-pus14ncitnstemy[pus14ncitnstemy$SCHL==23,]
pus14ncitnstemyd<-pus14ncitnstemy[pus14ncitnstemy$SCHL==24,]
# Then, I will calculate employment rates of different degrees in each category.
citstemdeg<-c(nrow(pus14citstemyb[!is.na(pus14citstemyb$OCCP),])/nrow(pus14citstemyb),nrow(pus14citstemym[!is.na(pus14citstemym$OCCP),])/nrow(pus14citstemym),nrow(pus14citstemyp[!is.na(pus14citstemyp$OCCP),])/nrow(pus14citstemyp),nrow(pus14citstemyd[!is.na(pus14citstemyd$OCCP),])/nrow(pus14citstemyd))
citnstemdeg<-c(nrow(pus14citnstemyb[!is.na(pus14citnstemyb$OCCP),])/nrow(pus14citnstemyb),nrow(pus14citnstemym[!is.na(pus14citnstemym$OCCP),])/nrow(pus14citnstemym),nrow(pus14citnstemyp[!is.na(pus14citnstemyp$OCCP),])/nrow(pus14citnstemyp),nrow(pus14citnstemyd[!is.na(pus14citnstemyd$OCCP),])/nrow(pus14citnstemyd))
ncitstemdeg<-c(nrow(pus14ncitstemyb[!is.na(pus14ncitstemyb$OCCP),])/nrow(pus14ncitstemyb),nrow(pus14ncitstemym[!is.na(pus14ncitstemym$OCCP),])/nrow(pus14ncitstemym),nrow(pus14ncitstemyp[!is.na(pus14ncitstemyp$OCCP),])/nrow(pus14ncitstemyp),nrow(pus14ncitstemyd[!is.na(pus14ncitstemyd$OCCP),])/nrow(pus14ncitstemyd))
ncitnstemdeg<-c(nrow(pus14ncitnstemyb[!is.na(pus14ncitnstemyb$OCCP),])/nrow(pus14ncitnstemyb),nrow(pus14ncitnstemym[!is.na(pus14ncitnstemym$OCCP),])/nrow(pus14ncitnstemym),nrow(pus14ncitnstemyp[!is.na(pus14ncitnstemyp$OCCP),])/nrow(pus14ncitnstemyp),nrow(pus14ncitnstemyd[!is.na(pus14ncitnstemyd$OCCP),])/nrow(pus14ncitnstemyd))
# Finally, I will visualize employment rates of different degrees in each category.
degmat<-rbind(citstemdeg,citnstemdeg,ncitstemdeg,ncitnstemdeg)
colnames(degmat)<-c("bachelor","master","professional","doctorate")
rownames(degmat)<-c("citizen STEM","citizen non-STEM","non-citizen STEM","non-citizen non-STEM")
degdf<-data.frame(degree=factor(rep(c("bachelor","master","professional","doctorate"),each=4),levels=c("bachelor","master","professional","doctorate")),status=factor(rep(c("citizen STEM","citizen non-STEM","non-citizen STEM","non-citizen non-STEM"),4)),rate=c(degmat[,1],degmat[,2],degmat[,3],degmat[,4]))
ggplot(data=degdf,aes(x=degree,y=rate,fill=status))+geom_bar(stat="identity",position=position_dodge())+geom_text(aes(label=round(rate,2)),position=position_dodge(width=0.9))+ggtitle("Employment Rate v.s. Degree/Citizenship Type") +
       theme(plot.title = element_text(size = rel(1),face="bold"))

(2) STEM degrees and STEM jobs

Now we want to have a closer look at how STEM degrees develop into STEM jobs. From these sankey plots, we see the component of STEM degrees and how STEM degree people separate into different industries after graduation for both citizens and non-citizens. First, apparantly, more people pursue a non-STEM degree. In STEM degrees, as for popularity, biology outperforms both CS and EE among citizens while it’s the opposite among non-citizens. This is quite reasonable since foreign students need to consider more about getting a job. For both STEM and non-STEM degree groups, the industry they choose after graduation varies a lot.

# In order to get top majors in both stem fields and non-stem fields, I need to obtain the frequency of each major in each data set and sort majors by frequencies for each data set.
topmajors14cit<-as.data.frame(sort(table(pus14cit$FOD1P),decreasing=T))
topmajors14ncit<-as.data.frame(sort(table(pus14ncit$FOD1P),decreasing=T))
colnames(topmajors14cit)<-"frequency"
colnames(topmajors14ncit)<-"frequency"
# Now, I generate stem/non-stem vectors for major vectors.
majorstemv14cit<-vector()
majorstemv14ncit<-vector()
for(i in 1:nrow(topmajors14cit)){
  majorstemv14cit[i]<-(pus14cit[pus14cit$FOD1P==as.numeric(rownames(topmajors14cit)[i]),which(colnames(pus14cit)=="STEM")])[1]
}
for(i in 1:nrow(topmajors14ncit)){
  majorstemv14ncit[i]<-(pus14ncit[pus14ncit$FOD1P==as.numeric(rownames(topmajors14ncit)[i]),which(colnames(pus14ncit)=="STEM")])[1]
}
# We need to generate major vs stem matrix now.
library(dplyr)
ms14cit<-topmajors14cit%>%mutate(major=rownames(topmajors14cit))
ms14cit<-ms14cit%>%mutate(stem=majorstemv14cit)
ms14cit<-ms14cit%>%mutate(proportion=frequency/sum(frequency))
ms14ncit<-topmajors14ncit%>%mutate(major=rownames(topmajors14ncit))
ms14ncit<-ms14ncit%>%mutate(stem=majorstemv14ncit)
ms14ncit<-ms14ncit%>%mutate(proportion=frequency/sum(frequency))
# Now, I will preprocess data for Sankey plot.
ms14citallns<-ms14cit%>%filter(stem==0)
ms14citalls<-ms14cit%>%filter(stem==1)
ms14cittopns<-rbind(ms14citallns[1:20,],c(sum(ms14citallns[-(1:20),1]),"other",0,sum(ms14citallns[-(1:20),4])))
ms14cittops<-rbind(ms14citalls[1:20,],c(sum(ms14citalls[-(1:20),1]),"other",1,sum(ms14citalls[-(1:20),4])))
ms14cittop<-rbind(ms14cittops,ms14cittopns)
ms14ncitallns<-ms14ncit%>%filter(stem==0)
ms14ncitalls<-ms14ncit%>%filter(stem==1)
ms14ncittopns<-rbind(ms14ncitallns[1:20,],c(sum(ms14ncitallns[-(1:20),1]),"other",0,sum(ms14ncitallns[-(1:20),4])))
ms14ncittops<-rbind(ms14ncitalls[1:20,],c(sum(ms14ncitalls[-(1:20),1]),"other",1,sum(ms14ncitalls[-(1:20),4])))
ms14ncittop<-rbind(ms14ncittops,ms14ncittopns)
# The following function is used to transfer major codes into major names
codename<-function(code){
  name<-"other"
  if(code==1100) name<-"general agriculture"
  if(code==1101) name<-"agriculture production and management"
  if(code==1102) name<-"agricultural economics"
  if(code==1103) name<-"animal sciences"
  if(code==1104) name<-"food science"
  if(code==1105) name<-"plant science and agronomy"
  if(code==1106) name<-"soil science"
  if(code==1199) name<-"miscellaneous agriculture"
  if(code==1301) name<-"environmental science"
  if(code==1302) name<-"forestry"
  if(code==1303) name<-"natural resources management"
  if(code==1401) name<-"architecture"
  if(code==1501) name<-"area ethnic and civilization"
  if(code==1901) name<-"communications"
  if(code==1902) name<-"journalism"
  if(code==1903) name<-"mass media"
  if(code==1904) name<-"advertising and public relations"
  if(code==2001) name<-"communication technologies"
  if(code==2100) name<-"computer and information systems"
  if(code==2101) name<-"computer programming and data processing"
  if(code==2102) name<-"computer science"
  if(code==2105) name<-"information sciences"
  if(code==2106) name<-"computer administration management and security"
  if(code==2107) name<-"computer networking and telecommunications"
  if(code==2201) name<-"cosmetology services and culinary arts"
  if(code==2300) name<-"general education"
  if(code==2301) name<-"educational administration and supervision"
  if(code==2303) name<-"school student counseling"
  if(code==2304) name<-"elementary education"
  if(code==2305) name<-"mathematics teacher education"
  if(code==2306) name<-"physical and health education teaching"
  if(code==2307) name<-"early childhood education"
  if(code==2308) name<-"science and computer teacher education"
  if(code==2309) name<-"secondary teacher education"
  if(code==2310) name<-"special needs education"
  if(code==2311) name<-"social science or history teacher education"
  if(code==2312) name<-"teacher education: multiple levels"
  if(code==2313) name<-"language and drama education"
  if(code==2314) name<-"art and music education"
  if(code==2399) name<-"miscellaneous education"
  if(code==2400) name<-"general engineering"
  if(code==2401) name<-"aerospace engineering"
  if(code==2402) name<-"biological engineering"
  if(code==2403) name<-"architectural engineering"
  if(code==2404) name<-"biomedical engineering"
  if(code==2405) name<-"chemical engineering"
  if(code==2406) name<-"civil engineering"
  if(code==2407) name<-"computer engineering"
  if(code==2408) name<-"electrical engineering"
  if(code==2409) name<-"engineering mechanics physics and science"
  if(code==2410) name<-"environmental engineering"
  if(code==2411) name<-"geological and geophysical engineering"
  if(code==2412) name<-"industrial and manufacturing engineering"
  if(code==2413) name<-"materials engneering and materials science"
  if(code==2414) name<-"mechanical engineering"
  if(code==2415) name<-"metallurgical engineering"
  if(code==2416) name<-"mining and mineral engineering"
  if(code==2417) name<-"naval architecture and marine engineering"
  if(code==2418) name<-"nuclear engineering"
  if(code==2419) name<-"petroleum engineering"
  if(code==2499) name<-"miscellaneous engineering"
  if(code==2500) name<-"engineering technologies"
  if(code==2501) name<-"engineering and industrial management"
  if(code==2502) name<-"electrical engineering technology"
  if(code==2503) name<-"industrial production technologies"
  if(code==2504) name<-"mechanical engineering related technologies"
  if(code==2599) name<-"miscellaneous engineering technologies"
  if(code==2601) name<-"linguistics and comparative language and literature"
  if(code==2602) name<-"french german latin and other common foreign language studies"
  if(code==2603) name<-"other foreign languages"
  if(code==2901) name<-"family and consumer sciences"
  if(code==3201) name<-"court reporting"
  if(code==3202) name<-"pre-law and legal studies"
  if(code==3301) name<-"english language and literature"
  if(code==3302) name<-"composition and rhetoric"
  if(code==3401) name<-"liberal arts"
  if(code==3402) name<-"humanities"
  if(code==3501) name<-"library science"
  if(code==3600) name<-"biology"
  if(code==3601) name<-"biochemical sciences"
  if(code==3602) name<-"botany"
  if(code==3603) name<-"molecular biology"
  if(code==3604) name<-"ecology"
  if(code==3605) name<-"genetics"
  if(code==3606) name<-"microbiology"
  if(code==3607) name<-"pharmacology"
  if(code==3608) name<-"physiology"
  if(code==3609) name<-"zoology"
  if(code==3611) name<-"neuroscience"
  if(code==3699) name<-"miscellaneous biology"
  if(code==3700) name<-"mathematics"
  if(code==3701) name<-"applied mathematics"
  if(code==3702) name<-"statistics and decision science"
  if(code==3801) name<-"military technologies"
  if(code==4000) name<-"multi/interdisciplinary studies"
  if(code==4001) name<-"intercultural and international studies"
  if(code==4002) name<-"nutrition sciences"
  if(code==4005) name<-"mathematics and computer science"
  if(code==4006) name<-"cognitive science and biopsychology"
  if(code==4007) name<-"interdisciplinary social sciences"
  if(code==4101) name<-"physical fitness parks recreation and leisure"
  if(code==4801) name<-"philosophy and religious studies"
  if(code==4901) name<-"theology and religious vocations"
  if(code==5000) name<-"physical sciences"
  if(code==5001) name<-"astronomy and astrophysics"
  if(code==5002) name<-"atmospheric sciences and meteorology"
  if(code==5003) name<-"chemistry"
  if(code==5004) name<-"geology and earth science"
  if(code==5005) name<-"geosciences"
  if(code==5006) name<-"oceanography"
  if(code==5007) name<-"physics"
  if(code==5008) name<-"material science"
  if(code==5098) name<-"multi-disciplinary or general science"
  if(code==5102) name<-"nuclear, industrial radiology, and biological technologies"
  if(code==5200) name<-"psychology"
  if(code==5201) name<-"educational psychology"
  if(code==5202) name<-"clinical psychology"
  if(code==5203) name<-"counseling psychology"
  if(code==5205) name<-"indsutrial and organizational psychology"
  if(code==5206) name<-"social psychology"
  if(code==5299) name<-"miscellaneous psychology"
  if(code==5301) name<-"criminal justice and fire protection"
  if(code==5401) name<-"public administration"
  if(code==5402) name<-"public policy"
  if(code==5403) name<-"human services and community organization"
  if(code==5404) name<-"social work"
  if(code==5500) name<-"general social sciences"
  if(code==5501) name<-"economics"
  if(code==5502) name<-"anthropology and archeology"
  if(code==5503) name<-"criminology"
  if(code==5504) name<-"geography"
  if(code==5505) name<-"internatinal relations"
  if(code==5506) name<-"political science and government"
  if(code==5507) name<-"sociology"
  if(code==5599) name<-"miscellaneous social sciences"
  if(code==5601) name<-"construction services"
  if(code==5701) name<-"electrical, mechanical and precision technologies and production"
  if(code==5901) name<-"transportation sciences and technologies"
  if(code==6000) name<-"fine arts"
  if(code==6001) name<-"drama and theater arts"
  if(code==6002) name<-"music"
  if(code==6003) name<-"visual and performing arts"
  if(code==6004) name<-"commercial arts and graphic design"
  if(code==6005) name<-"film video and photographic arts"
  if(code==6006) name<-"art history and criticism"
  if(code==6007) name<-"studio arts"
  if(code==6099) name<-"miscellaneous fine arts"
  if(code==6100) name<-"general medical and health services"
  if(code==6102) name<-"communication disorders sciences and services"
  if(code==6103) name<-"health and medical administrative services"
  if(code==6104) name<-"medical assisting services"
  if(code==6105) name<-"medical technologies technicians"
  if(code==6106) name<-"health and medical preparatory programs"
  if(code==6107) name<-"nursing"
  if(code==6108) name<-"pharmacy pharmaceutical sciences and administration"
  if(code==6109) name<-"treatment therapy professions"
  if(code==6110) name<-"community and public health"
  if(code==6199) name<-"miscellaneous health medical professions"
  if(code==6200) name<-"general business"
  if(code==6201) name<-"accounting"
  if(code==6202) name<-"actuarial science"
  if(code==6203) name<-"business management and administration"
  if(code==6204) name<-"operations logistics and e-commerce"
  if(code==6205) name<-"business economics"
  if(code==6206) name<-"marketing and marketing research"
  if(code==6207) name<-"finance"
  if(code==6209) name<-"human resources and personnel management"
  if(code==6210) name<-"international business"
  if(code==6211) name<-"hospitality management"
  if(code==6212) name<-"management information systems and statistics"
  if(code==6299) name<-"miscellaneous business and medical administration"
  if(code==6402) name<-"history"
  if(code==6403) name<-"united states history"
  return(name)
}
# Then I will transfer major codes to major names and stem code to stem/non-stem.
for(i in 1:nrow(ms14cittop)){
  ms14cittop[i,which(colnames(ms14cittop)=="major")]<-codename(ms14cittop$major[i])
}
for(i in 1:nrow(ms14ncittop)){
  ms14ncittop[i,which(colnames(ms14ncittop)=="major")]<-codename(ms14ncittop$major[i])
}
ms14cittop[ms14cittop$stem==1,which(colnames(ms14cittop)=="stem")]<-"stem"
ms14cittop[ms14cittop$stem==0,which(colnames(ms14cittop)=="stem")]<-"non-stem"
ms14ncittop[ms14ncittop$stem==1,which(colnames(ms14ncittop)=="stem")]<-"stem"
ms14ncittop[ms14ncittop$stem==0,which(colnames(ms14ncittop)=="stem")]<-"non-stem"
# ms14cittop, ms14ncittop will be used later.
# Now, I need to do stem vs occupation type.
stemwork14cit<-pus14cit%>%filter(STEM==1)
stemwork14ncit<-pus14ncit%>%filter(STEM==1)
nstemwork14cit<-pus14cit%>%filter(STEM==0)
nstemwork14ncit<-pus14ncit%>%filter(STEM==0)
topstemwork14cit<-as.data.frame(sort(table(stemwork14cit$OCCP.TYPE),decreasing=T))
topstemwork14ncit<-as.data.frame(sort(table(stemwork14ncit$OCCP.TYPE),decreasing=T))
topnstemwork14cit<-as.data.frame(sort(table(nstemwork14cit$OCCP.TYPE),decreasing=T))
topnstemwork14ncit<-as.data.frame(sort(table(nstemwork14ncit$OCCP.TYPE),decreasing=T))
topstemwork14cit<-cbind(topstemwork14cit,c("stem"))
topstemwork14ncit<-cbind(topstemwork14ncit,c("stem"))
topnstemwork14cit<-cbind(topnstemwork14cit,c("non-stem"))
topnstemwork14ncit<-cbind(topnstemwork14ncit,c("non-stem"))
colnames(topstemwork14cit)<-c("frequency","stem")
colnames(topstemwork14ncit)<-c("frequency","stem")
colnames(topnstemwork14cit)<-c("frequency","stem")
colnames(topnstemwork14ncit)<-c("frequency","stem")
topstemwork14cit<-topstemwork14cit%>%mutate(work=rownames(topstemwork14cit))
topstemwork14ncit<-topstemwork14ncit%>%mutate(work=rownames(topstemwork14ncit))
topnstemwork14cit<-topnstemwork14cit%>%mutate(work=rownames(topnstemwork14cit))
topnstemwork14ncit<-topnstemwork14ncit%>%mutate(work=rownames(topnstemwork14ncit))
topwork14cit<-rbind(topstemwork14cit,topnstemwork14cit)
topwork14ncit<-rbind(topstemwork14ncit,topnstemwork14ncit)
topwork14cit[topwork14cit$work=="0",which(colnames(topwork14cit)=="work")]<-"NONE"
topwork14ncit[topwork14ncit$work=="0",which(colnames(topwork14ncit)=="work")]<-"NONE"
topwork14cit<-topwork14cit%>%mutate(proportion=frequency/sum(frequency))
topwork14ncit<-topwork14ncit%>%mutate(proportion=frequency/sum(frequency))
# topwork14cit,topwork14ncit will be used.
# Now, I am ready for Sankey plot.
msw14cit1<-ms14cittop[,2:4]
colnames(msw14cit1)<-c("origin","visit","weight")
msw14cit2<-topwork14cit[,2:4]
colnames(msw14cit2)<-c("origin","visit","weight")
msw14cit<-rbind(msw14cit1,msw14cit2)
msw14cit[,1]<-as.factor(msw14cit[,1])
msw14cit[,2]<-as.factor(msw14cit[,2])
msw14cit[,3]<-as.numeric(msw14cit[,3])
msw14ncit1<-ms14ncittop[,2:4]
colnames(msw14ncit1)<-c("origin","visit","weight")
msw14ncit2<-topwork14ncit[,2:4]
colnames(msw14ncit2)<-c("origin","visit","weight")
msw14ncit<-rbind(msw14ncit1,msw14ncit2)
msw14ncit[,1]<-as.factor(msw14ncit[,1])
msw14ncit[,2]<-as.factor(msw14ncit[,2])
msw14ncit[,3]<-as.numeric(msw14ncit[,3])
For citizens:
library(googleVis)
op<-options(gvis.plot.tag='chart')
sankeycit<-gvisSankey(msw14cit,from="origin",to="visit",weight="weight",options=list(height=700,width=900,sankey="{link:{color:{fill:'deepskyblue'}},node:{width:20,label:{fontSize:12,bold:true}}}"))
plot(sankeycit)
For non-citizens:
sankeynoncit<-gvisSankey(msw14ncit,from="origin",to="visit",weight="weight",options=list(height=700,width=900,sankey="{link:{color:{fill:'mediumspringgreen'}},node:{width:20,label:{fontSize:12,bold:true}}}"))
print(sankeynoncit,'chart')
options(op)

(3) Industry Choice After Graduation

To further study how people of specific STEM degree go into different industries, we draw the following circular plots. Each plot corresponses to either citizen or non-citizen and either STEM degree or non-STEM degree. These figures suggest a lot of information but due to the time constraints, we will not talk about them during this presentation.

# Now, I will do circular plots for majors in stem vs occupation and majors in non-stem vs occupation for citizens and non-citizens.
pus14citstem<-pus14cit[pus14cit$STEM==1,]
pus14citnstem<-pus14cit[pus14cit$STEM==0,]
pus14ncitstem<-pus14ncit[pus14ncit$STEM==1,]
pus14ncitnstem<-pus14ncit[pus14ncit$STEM==0,]
# each top major
pus14citstemtop<-list()
for(i in 1:10){
  pus14citstemtop[[i]]<-pus14citstem%>%filter(FOD1P==as.numeric(ms14cittops$major[i]))
}
pus14citnstemtop<-list()
for(i in 1:10){
  pus14citnstemtop[[i]]<-pus14citnstem%>%filter(FOD1P==as.numeric(ms14cittopns$major[i]))
}
pus14ncitstemtop<-list()
for(i in 1:10){
  pus14ncitstemtop[[i]]<-pus14ncitstem%>%filter(FOD1P==as.numeric(ms14ncittops$major[i]))
}
pus14ncitnstemtop<-list()
for(i in 1:10){
  pus14ncitnstemtop[[i]]<-pus14ncitnstem%>%filter(FOD1P==as.numeric(ms14ncittopns$major[i]))
}
# amount of jobs in each field for each top major
citstemf14<-list()
for(i in 1:10){
  citstemf14[[i]]<-as.data.frame(sort(table(pus14citstemtop[[i]]$OCCP.TYPE),decreasing=T))
}
citnstemf14<-list()
for(i in 1:10){
  citnstemf14[[i]]<-as.data.frame(sort(table(pus14citnstemtop[[i]]$OCCP.TYPE),decreasing=T))
}
ncitstemf14<-list()
for(i in 1:10){
  ncitstemf14[[i]]<-as.data.frame(sort(table(pus14ncitstemtop[[i]]$OCCP.TYPE),decreasing=T))
}
ncitnstemf14<-list()
for(i in 1:10){
  ncitnstemf14[[i]]<-as.data.frame(sort(table(pus14ncitnstemtop[[i]]$OCCP.TYPE),decreasing=T))
}
for(i in 1:10){
  citstemf14[[i]]<-citstemf14[[i]]%>%mutate(type=rownames(citstemf14[[i]]))
  citnstemf14[[i]]<-citnstemf14[[i]]%>%mutate(type=rownames(citnstemf14[[i]]))
  ncitstemf14[[i]]<-ncitstemf14[[i]]%>%mutate(type=rownames(ncitstemf14[[i]]))
  ncitnstemf14[[i]]<-ncitnstemf14[[i]]%>%mutate(type=rownames(ncitnstemf14[[i]]))
  colnames(citstemf14[[i]])[1]<-"frequency"
  colnames(citnstemf14[[i]])[1]<-"frequency"
  colnames(ncitstemf14[[i]])[1]<-"frequency"
  colnames(ncitnstemf14[[i]])[1]<-"frequency"
}
for(i in 1:10){
  citstemf14[[i]]<-citstemf14[[i]][order(citstemf14[[i]]$type),]
  citnstemf14[[i]]<-citnstemf14[[i]][order(citnstemf14[[i]]$type),]
  ncitstemf14[[i]]<-ncitstemf14[[i]][order(ncitstemf14[[i]]$type),]
  ncitnstemf14[[i]]<-ncitnstemf14[[i]][order(ncitnstemf14[[i]]$type),]
}
citstemm14<-matrix(0,nrow=10,ncol=25)
citnstemm14<-matrix(0,nrow=10,ncol=25)
ncitstemm14<-matrix(0,nrow=10,ncol=25)
ncitnstemm14<-matrix(0,nrow=10,ncol=25)
for(i in 1:10){
  citstemm14[i,]<-citstemf14[[i]]$frequency[2:26]
  citnstemm14[i,]<-citnstemf14[[i]]$frequency[2:26]
  ncitstemm14[i,]<-ncitstemf14[[i]]$frequency[2:26]
  ncitnstemm14[i,]<-ncitnstemf14[[i]]$frequency[2:26]
}
colnames(citstemm14)<-citstemf14[[1]]$type[2:26]
colnames(citnstemm14)<-citnstemf14[[1]]$type[2:26]
colnames(ncitstemm14)<-ncitstemf14[[1]]$type[2:26]
colnames(ncitnstemm14)<-ncitnstemf14[[1]]$type[2:26]
rownames(citstemm14)<-c(1,2,3,4,5,6,7,8,9,10)
rownames(citnstemm14)<-c(1,2,3,4,5,6,7,8,9,10)
rownames(ncitstemm14)<-c(1,2,3,4,5,6,7,8,9,10)
rownames(ncitnstemm14)<-c(1,2,3,4,5,6,7,8,9,10)
for(i in 1:10){
  rownames(citstemm14)[i]<-codename(ms14cittops$major[i])
  rownames(citnstemm14)[i]<-codename(ms14cittopns$major[i])
  rownames(ncitstemm14)[i]<-codename(ms14ncittops$major[i])
  rownames(ncitnstemm14)[i]<-codename(ms14ncittopns$major[i])
}
visualization #1 Citizen STEM
library(recharts)
zero1010<-matrix(0,10,10)
zero2525<-matrix(0,25,25)
citstemm14c1<-cbind(zero1010,citstemm14)
citstemm14c2<-cbind(t(citstemm14),zero2525)
citstemm14c<-rbind(citstemm14c1,citstemm14c2)
chordcitstem=list(title=list(text='Citizen STEM',subtext='From JavaScript',x='right',y='bottom'),
tooltip=list(trigger='item',formatter=JS('function(params){
                      if (params.indicator2) { // is edge
                        return params.value.weight;
                      } else {// is node
                        return params.name
                      }
                                                           }')),
toolbox=list(show=TRUE,feature=list(restore=list(show=TRUE),magicType=list(show=TRUE,type=c('force','chord')),
saveAsImage=list(show=TRUE))),
legend=list(x='left',data=c(rownames(citstemm14),colnames(citstemm14))),
series=list(list(type='chord',showScale=FALSE,showScaleText=FALSE,
data=list(list(name=rownames(citstemm14)[1]),list(name=rownames(citstemm14)[2]),list(name=rownames(citstemm14)[3]),list(name=rownames(citstemm14)[4]),list(name=rownames(citstemm14)[5]),list(name=rownames(citstemm14)[6]),list(name=rownames(citstemm14)[7]),list(name=rownames(citstemm14)[8]),list(name=rownames(citstemm14)[9]),list(name=rownames(citstemm14)[10]),list(name=colnames(citstemm14)[1]),list(name=colnames(citstemm14)[2]),list(name=colnames(citstemm14)[3]),list(name=colnames(citstemm14)[4]),list(name=colnames(citstemm14)[5]),list(name=colnames(citstemm14)[6]),list(name=colnames(citstemm14)[7]),list(name=colnames(citstemm14)[8]),list(name=colnames(citstemm14)[9]),list(name=colnames(citstemm14)[10]),list(name=colnames(citstemm14)[11]),list(name=colnames(citstemm14)[12]),list(name=colnames(citstemm14)[13]),list(name=colnames(citstemm14)[14]),list(name=colnames(citstemm14)[15]),list(name=colnames(citstemm14)[16]),list(name=colnames(citstemm14)[17]),list(name=colnames(citstemm14)[18]),list(name=colnames(citstemm14)[19]),list(name=colnames(citstemm14)[20]),list(name=colnames(citstemm14)[21]),list(name=colnames(citstemm14)[22]),list(name=colnames(citstemm14)[23]),list(name=colnames(citstemm14)[24]),list(name=colnames(citstemm14)[25])),
itemStyle=list(normal=list(label=list(show=TRUE))),
matrix=citstemm14c)))
echart(chordcitstem)
visualization #2 Citizen Non-STEM
zero1010<-matrix(0,10,10)
zero2525<-matrix(0,25,25)
citnstemm14c1<-cbind(zero1010,citnstemm14)
citnstemm14c2<-cbind(t(citnstemm14),zero2525)
citnstemm14c<-rbind(citnstemm14c1,citnstemm14c2)
chordcitnstem=list(title=list(text='Citizen non-STEM',subtext='From JavaScript',x='right',y='bottom'),
tooltip=list(trigger='item',formatter=JS('function(params){
                      if (params.indicator2) { // is edge
                        return params.value.weight;
                      } else {// is node
                        return params.name
                      }
                                                           }')),
toolbox=list(show=TRUE,feature=list(restore=list(show=TRUE),magicType=list(show=TRUE,type=c('force','chord')),
saveAsImage=list(show=TRUE))),
legend=list(x='left',data=c(rownames(citnstemm14),colnames(citnstemm14))),
series=list(list(type='chord',showScale=FALSE,showScaleText=FALSE,
data=list(list(name=rownames(citnstemm14)[1]),list(name=rownames(citnstemm14)[2]),list(name=rownames(citnstemm14)[3]),list(name=rownames(citnstemm14)[4]),list(name=rownames(citnstemm14)[5]),list(name=rownames(citnstemm14)[6]),list(name=rownames(citnstemm14)[7]),list(name=rownames(citnstemm14)[8]),list(name=rownames(citnstemm14)[9]),list(name=rownames(citnstemm14)[10]),list(name=colnames(citnstemm14)[1]),list(name=colnames(citnstemm14)[2]),list(name=colnames(citnstemm14)[3]),list(name=colnames(citnstemm14)[4]),list(name=colnames(citnstemm14)[5]),list(name=colnames(citnstemm14)[6]),list(name=colnames(citnstemm14)[7]),list(name=colnames(citnstemm14)[8]),list(name=colnames(citnstemm14)[9]),list(name=colnames(citnstemm14)[10]),list(name=colnames(citnstemm14)[11]),list(name=colnames(citnstemm14)[12]),list(name=colnames(citnstemm14)[13]),list(name=colnames(citnstemm14)[14]),list(name=colnames(citnstemm14)[15]),list(name=colnames(citnstemm14)[16]),list(name=colnames(citnstemm14)[17]),list(name=colnames(citnstemm14)[18]),list(name=colnames(citnstemm14)[19]),list(name=colnames(citnstemm14)[20]),list(name=colnames(citnstemm14)[21]),list(name=colnames(citnstemm14)[22]),list(name=colnames(citnstemm14)[23]),list(name=colnames(citnstemm14)[24]),list(name=colnames(citnstemm14)[25])),
itemStyle=list(normal=list(label=list(show=TRUE))),
matrix=citnstemm14c)))
echart(chordcitnstem)
visualization #3 Non-Citizen STEM
zero1010<-matrix(0,10,10)
zero2525<-matrix(0,25,25)
ncitstemm14c1<-cbind(zero1010,ncitstemm14)
ncitstemm14c2<-cbind(t(ncitstemm14),zero2525)
ncitstemm14c<-rbind(ncitstemm14c1,ncitstemm14c2)
chordncitstem=list(title=list(text='non-Citizen STEM',subtext='From JavaScript',x='right',y='bottom'),
tooltip=list(trigger='item',formatter=JS('function(params){
                      if (params.indicator2) { // is edge
                        return params.value.weight;
                      } else {// is node
                        return params.name
                      }
                                                           }')),
toolbox=list(show=TRUE,feature=list(restore=list(show=TRUE),magicType=list(show=TRUE,type=c('force','chord')),
saveAsImage=list(show=TRUE))),
legend=list(x='left',data=c(rownames(ncitstemm14),colnames(ncitstemm14))),
series=list(list(type='chord',showScale=FALSE,showScaleText=FALSE,
data=list(list(name=rownames(ncitstemm14)[1]),list(name=rownames(ncitstemm14)[2]),list(name=rownames(ncitstemm14)[3]),list(name=rownames(ncitstemm14)[4]),list(name=rownames(ncitstemm14)[5]),list(name=rownames(ncitstemm14)[6]),list(name=rownames(ncitstemm14)[7]),list(name=rownames(ncitstemm14)[8]),list(name=rownames(ncitstemm14)[9]),list(name=rownames(ncitstemm14)[10]),list(name=colnames(ncitstemm14)[1]),list(name=colnames(ncitstemm14)[2]),list(name=colnames(ncitstemm14)[3]),list(name=colnames(ncitstemm14)[4]),list(name=colnames(ncitstemm14)[5]),list(name=colnames(ncitstemm14)[6]),list(name=colnames(ncitstemm14)[7]),list(name=colnames(ncitstemm14)[8]),list(name=colnames(ncitstemm14)[9]),list(name=colnames(ncitstemm14)[10]),list(name=colnames(ncitstemm14)[11]),list(name=colnames(ncitstemm14)[12]),list(name=colnames(ncitstemm14)[13]),list(name=colnames(ncitstemm14)[14]),list(name=colnames(ncitstemm14)[15]),list(name=colnames(ncitstemm14)[16]),list(name=colnames(ncitstemm14)[17]),list(name=colnames(ncitstemm14)[18]),list(name=colnames(ncitstemm14)[19]),list(name=colnames(ncitstemm14)[20]),list(name=colnames(ncitstemm14)[21]),list(name=colnames(ncitstemm14)[22]),list(name=colnames(ncitstemm14)[23]),list(name=colnames(ncitstemm14)[24]),list(name=colnames(ncitstemm14)[25])),
itemStyle=list(normal=list(label=list(show=TRUE))),
matrix=ncitstemm14c)))
echart(chordncitstem)
visualization #4 Non-Citizen Non-STEM
zero1010<-matrix(0,10,10)
zero2525<-matrix(0,25,25)
ncitnstemm14c1<-cbind(zero1010,ncitnstemm14)
ncitnstemm14c2<-cbind(t(ncitnstemm14),zero2525)
ncitnstemm14c<-rbind(ncitnstemm14c1,ncitnstemm14c2)
chordncitnstem=list(title=list(text='non-Citizen non-STEM',subtext='From JavaScript',x='right',y='bottom'),
tooltip=list(trigger='item',formatter=JS('function(params){
                      if (params.indicator2) { // is edge
                        return params.value.weight;
                      } else {// is node
                        return params.name
                      }
                                                           }')),
toolbox=list(show=TRUE,feature=list(restore=list(show=TRUE),magicType=list(show=TRUE,type=c('force','chord')),
saveAsImage=list(show=TRUE))),
legend=list(x='left',data=c(rownames(ncitnstemm14),colnames(ncitnstemm14))),
series=list(list(type='chord',showScale=FALSE,showScaleText=FALSE,
data=list(list(name=rownames(ncitnstemm14)[1]),list(name=rownames(ncitnstemm14)[2]),list(name=rownames(ncitnstemm14)[3]),list(name=rownames(ncitnstemm14)[4]),list(name=rownames(ncitnstemm14)[5]),list(name=rownames(ncitnstemm14)[6]),list(name=rownames(ncitnstemm14)[7]),list(name=rownames(ncitnstemm14)[8]),list(name=rownames(ncitnstemm14)[9]),list(name=rownames(ncitnstemm14)[10]),list(name=colnames(ncitnstemm14)[1]),list(name=colnames(ncitnstemm14)[2]),list(name=colnames(ncitnstemm14)[3]),list(name=colnames(ncitnstemm14)[4]),list(name=colnames(ncitnstemm14)[5]),list(name=colnames(ncitnstemm14)[6]),list(name=colnames(ncitnstemm14)[7]),list(name=colnames(ncitnstemm14)[8]),list(name=colnames(ncitnstemm14)[9]),list(name=colnames(ncitnstemm14)[10]),list(name=colnames(ncitnstemm14)[11]),list(name=colnames(ncitnstemm14)[12]),list(name=colnames(ncitnstemm14)[13]),list(name=colnames(ncitnstemm14)[14]),list(name=colnames(ncitnstemm14)[15]),list(name=colnames(ncitnstemm14)[16]),list(name=colnames(ncitnstemm14)[17]),list(name=colnames(ncitnstemm14)[18]),list(name=colnames(ncitnstemm14)[19]),list(name=colnames(ncitnstemm14)[20]),list(name=colnames(ncitnstemm14)[21]),list(name=colnames(ncitnstemm14)[22]),list(name=colnames(ncitnstemm14)[23]),list(name=colnames(ncitnstemm14)[24]),list(name=colnames(ncitnstemm14)[25])),
itemStyle=list(normal=list(label=list(show=TRUE))),
matrix=ncitnstemm14c)))
echart(chordncitnstem)

Part 2. Influences of STEM policy on employees

1. Our Objective

In this part of analysis, we want to know how STEM jobs have changed along with the announcement of the STEM policy. Two data sets are being used: data of 2007, which is the last year before STEM policy, and data of 2014, the latest obtainable under-STEM-policy data. For each data set, we categorize our data into two classes: STEM-job data and non-STEM-job data. By doing the separations, we can look at the differences of STEM and non-STEM jobs before and after STEM policy went out.

2. Our Concerns

  1. Will the STEM/non-STEM job allocation change?

  2. Among STEM/non-STEM jobs, will gender proportion and class of work be influenced by the STEM policy?

  3. How did the working conditions, such as wage and working hours change?

  4. Will the STEM policy further influence people’s immigration behavior?

3. Our Findings

The first thing we studied is whether the STEM/non-STEM job allocation has changed geographically. According to the first two figures, we can see that the allocation of non-STEM jobs barely changed after STEM policy went out. According to the last two figures, we see for STEM jobs, something happened on the east coast.

library(data.table)
library(dplyr)
library(ggplot2)
library(fmsb)
library(choroplethr)
library(choroplethrMaps)

# read data
cols <- c("WAGP", "ST", "AGEP", "ESR", "CIT", "YOEP", "COW", "SEX" , "WKHP","WKW","SOCP","POWSP","POVPIP","SCHL")

before_data11<-fread("/Users/YaqingXie/Desktop/Applied Data Science/Week1/csv_pus(2007)/ss07pusa.csv", select=cols)
before_data12<-fread("/Users/YaqingXie/Desktop/Applied Data Science/Week1/csv_pus(2007)/ss07pusa.csv", select=c(160:239))
before_data21<-fread("/Users/YaqingXie/Desktop/Applied Data Science/Week1/csv_pus(2007)/ss07pusb.csv", select=cols)
before_data22<-fread("/Users/YaqingXie/Desktop/Applied Data Science/Week1/csv_pus(2007)/ss07pusb.csv", select=c(160:239))
before_data1 <- cbind(before_data11, before_data12)
before_data2 <- cbind(before_data21, before_data22)
before_data<- subset(rbind(before_data1, before_data2))

after_data11<-fread("/Users/YaqingXie/Desktop/Applied Data Science/Week1/csv_pus/ss14pusa.csv", select=cols)
after_data12<-fread("/Users/YaqingXie/Desktop/Applied Data Science/Week1/csv_pus/ss14pusa.csv", select=c(205:284))
after_data21<-fread("/Users/YaqingXie/Desktop/Applied Data Science/Week1/csv_pus/ss14pusb.csv", select=cols)
after_data22<-fread("/Users/YaqingXie/Desktop/Applied Data Science/Week1/csv_pus/ss14pusb.csv", select=c(205:284))
after_data1 <- cbind(after_data11, after_data12)
after_data2 <- cbind(after_data21, after_data22)
after_data<- subset(rbind(after_data1, after_data2))

#filter data: only people currenlty employeed in US
before_data<-before_data[!(before_data$ESR %in% c(3,6,NA))]
before_data<-before_data[before_data$POWSP >= 1 & before_data$POWSP <= 56]
after_data<-after_data[!(after_data$ESR %in% c(3,6,NA))]
after_data<-after_data[after_data$POWSP >= 1 & after_data$POWSP <= 56]

# job code for STEM occupations
# source: http://www.bls.gov/soc/Attachment_C_STEM.pdf
before_stem_job_codes = c('113021','119041','119111','119121','151021','151030','151041','151061','151071','151081','1510XX','152011','152031','1520XX','171010','171020','172011','172041','172051','172061','172070','172081','1720XX','172110','172121','172131','172141','1721XX','1721YY','173010','173020','173031','191010','191020','191030','191040','192010','192021','192030','192040','192099','193011','193020','193030','193051','1930XX','194011','194021','194031','194041','1940XX','254010','291011','291020','291031','291041','291051','291060','291071','291081','291111','291121','291122','291123','291124','291125','291126','291127','291129','291131','291199','292010','292021','292030','292041','292050','292061','292071','292081','292090','299000','414010','419031')
after_stem_job_codes = c('113021','119041','119121','151111','151121','151122','151131','151132','151133','151134','151141','151142','151143','151151','151152','151199','152011','152021','152031','152041','152099','171021','171022','172011','172021','172031','172041','172051','172061','172071','172072','172081','172111','172112','172121','172131','172141','172151','172161','172171','172199','173012','173013','173019','173021','173022','173023','173024','173025','173026','173027','173029','173031','191011','191012','191012','191021','191022','191023','191029','191031','191032','191041','191042','191099','192011','192012','192021','192031','192032','192041','192042','192043','192099','194011','194021','194031','194041','194051','194091','194092','194093','251021','251022','251032','251041','251042','251043','251051','251052','251053','251054','414011','419031')

# categorize job into stem and non-stem
before_data$SOCP[!(before_data$SOCP %in% before_stem_job_codes) & (before_data$SOCP!="")] <- "NON-STEM"
before_data$SOCP[before_data$SOCP %in% before_stem_job_codes] <- "STEM"
after_data$SOCP[!(after_data$SOCP %in% after_stem_job_codes) & (after_data$SOCP!="")] <- "NON-STEM"
after_data$SOCP[after_data$SOCP %in% after_stem_job_codes] <- "STEM"

# rename gender
before_data$SEX[before_data$SEX == 1] <- "Male"
before_data$SEX[before_data$SEX == 2] <- "Female"
after_data$SEX[after_data$SEX == 1] <- "Male"
after_data$SEX[after_data$SEX == 2] <- "Female"

# rename class of worker
before_data$COW[before_data$COW == 1] <- "For-profit Company"
before_data$COW[before_data$COW == 2] <- "Not-for-profit Organization"
before_data$COW[before_data$COW == 3] <- "Local Government"
before_data$COW[before_data$COW == 4] <- "State Government"
before_data$COW[before_data$COW == 5] <- "Federal Government"
before_data$COW[before_data$COW == 6] <- "Self-employeed & Not Incorporated"
before_data$COW[before_data$COW == 7] <- "Self-employeed & Incorporated"
before_data$COW[before_data$COW == 8] <- "Family Business"
after_data$COW[after_data$COW == 1] <- "For-profit Company"
after_data$COW[after_data$COW == 2] <- "Not-for-profit Organization"
after_data$COW[after_data$COW == 3] <- "Local Government"
after_data$COW[after_data$COW == 4] <- "State Government"
after_data$COW[after_data$COW == 5] <- "Federal Government"
after_data$COW[after_data$COW == 6] <- "Self-employeed & Not Incorporated"
after_data$COW[after_data$COW == 7] <- "Self-employeed & Incorporated"
after_data$COW[after_data$COW == 8] <- "Family Business"

# recode number of weeks worked in the past year
after_data$WKW[after_data$WKW==1] <- 51
after_data$WKW[after_data$WKW==2] <- 48.5
after_data$WKW[after_data$WKW==3] <- 43.5
after_data$WKW[after_data$WKW==4] <- 33
after_data$WKW[after_data$WKW==5] <- 20
after_data$WKW[after_data$WKW==6] <- 7

(1) Job Allocation in US

# plotting
# 1 POWSP-stem/nonstem-before/after  MAP
before_stem <- before_data[before_data$SOCP == 'STEM']
before_state_stem <- subset(before_stem, select=c("ST","POWSP"))
before_nonstem <- before_data[before_data$SOCP == 'NON-STEM']
before_state_nonstem <- subset(before_nonstem, select=c("ST","POWSP"))
after_stem <- after_data[after_data$SOCP == 'STEM']
after_state_stem <- subset(after_stem, select=c("ST","POWSP"))
after_nonstem <- after_data[after_data$SOCP == 'NON-STEM']
after_state_nonstem <- subset(after_nonstem, select=c("ST","POWSP"))
data("state.regions")
statenames <- data.frame(cbind(state.regions[,1],state.regions[,3]))
names(statenames) <- c('region', 'region_code')
getstate <- function(vector){
  temp <- data.frame(vector)
  names(temp) <- c("region_code")
  new_dataframe <- merge(temp,statenames, by.x="region_code", by.y='region_code')
  new_dataframe <- table(new_dataframe$region)
  new_dataframe <- data.frame(new_dataframe)
  names(new_dataframe) <- c('region','value')
  return(new_dataframe)
}
before_stem_ST <- getstate(before_state_stem$ST)
before_stem_POW <- getstate(before_state_stem$POWSP)
before_nonstem_ST <- getstate(before_state_nonstem$ST)
before_nonstem_POW <- getstate(before_state_nonstem$POWSP)
after_stem_ST <- getstate(after_state_stem$ST)
after_stem_POW <- getstate(after_state_stem$POWSP)
after_nonstem_ST <- getstate(after_state_nonstem$ST)
after_nonstem_POW <- getstate(after_state_nonstem$POWSP)
state_choropleth(before_nonstem_POW,
                 title      = "Before STEM Policy: NON-STEM Job Allocation",
                 legend     = "Number of Occupations",
                 num_colors = 1)
joining factor and character vector, coercing into character vector

state_choropleth(after_nonstem_POW,
                 title      = "After STEM Policy: NON-STEM Job Allocation",
                 legend     = "Number of Occupations",
                 num_colors = 1)
joining factor and character vector, coercing into character vector

state_choropleth(before_stem_POW,
                 title      = "Before STEM Policy: STEM Job Allocation",
                 legend     = "Number of Occupations",
                 num_colors = 1)
joining factor and character vector, coercing into character vector

state_choropleth(after_stem_POW,
                 title      = "After STEM Policy: STEM Job Allocation",
                 legend     = "Number of Occupations",
                 num_colors = 1)
joining factor and character vector, coercing into character vector

If we take a closer look at these states, we can see relevant jobs in NY and FL tended to diffuse towards neighboring states, among which, Virginia has the most significant increase in terms of the amount of STEM jobs.

state_choropleth(before_stem_POW,
                 title      = "Before STEM Policy: STEM Job Allocation",
                 legend     = "Number of Occupations",
                 num_colors = 1,
                 zoom = c("new york","pennsylvania","virginia","ohio","north carolina","south carolina","georgia","florida"))
joining factor and character vector, coercing into character vector

state_choropleth(after_stem_POW,
                 title      = "After STEM Policy: STEM Job Allocation",
                 legend     = "Number of Occupations",
                 num_colors = 1,
                 zoom = c("new york","pennsylvania","virginia","ohio","north carolina","south carolina","georgia","florida"))
joining factor and character vector, coercing into character vector

In general, the state allocation of jobs didn’t change dramatically after the STEM policy went out. It could be plausible since STEM policy is in effect for foreign students while the job allocation depends more on the locational choices of different companies.

(2) Working Conditions: What to Pay and What to Get

The second figure we got is a radar chart considering income, working hours/weeks, degree level and income-to-poverty index.

STEM jobs used to be the kind of jobs in which you need to pay more in order to get more. The good thing was, you didn’t need to have an advanced degree to get such kind of jobs. Howeverm after STEM policy went out, the requirement of degree in STEM jobs raised sharply. Though the change in non-STEM jobs is great too, STEM jobs are still the group which requires the highest average degree attainment.

We can also read more information from this figure, such as, currently, the better income/degree performance appears to STEM jobs instead of non-STEM jobs and the gap is quite obvious. However, speaking of income/working hours, non-STEM job could be a better choice.

# 2 wage&wkhp&wkw&povpip&schl-stem/nonstem-before/after
# survey weight
library(survey)
#df_before<-svrepdesign(variables=before_data[,1:16], 
#                 repweights=before_data[,17:86], type="BRR",combined.weights=TRUE,
#                 weights=before_data$PWGTP)
#summary(df_before)
#svymean(~ WAGP,df_before, na.rm = T)
#df_after<-svrepdesign(variables=after_data[,1:16], 
#                       repweights=after_data[,17:86], type="BRR",combined.weights=TRUE,
#                       weights=after_data$PWGTP)
#summary(df_before)
#svymean(~ WAGP,df_before, na.rm = T)
radardata <- data.frame(group = character(), wage = numeric(), hr_per_wk = numeric, wk_per_yr = numeric(), income_to_poverty = numeric(), degree = numeric())
radardata <- rbind(radardata, data.frame(group = "before_stem", wage = mean(before_stem$WAGP), hr_per_wk=mean(before_stem$WKHP), wk_per_yr=mean(before_stem$WKW), income_to_poverty=mean(before_stem$POVPIP,na.rm=TRUE), degree=mean(before_stem$SCHL)))
radardata <- rbind(radardata, data.frame(group = "before_nonstem", wage = mean(before_nonstem$WAGP), hr_per_wk=mean(before_nonstem$WKHP), wk_per_yr=mean(before_nonstem$WKW), income_to_poverty=mean(before_nonstem$POVPIP,na.rm=TRUE), degree=mean(before_nonstem$SCHL)))
radardata <- rbind(radardata, data.frame(group = "after_stem", wage = mean(after_stem$WAGP), hr_per_wk=mean(after_stem$WKHP), wk_per_yr=mean(after_stem$WKW), income_to_poverty=mean(after_stem$POVPIP,na.rm=TRUE), degree=mean(after_stem$SCHL)))
radardata <- rbind(radardata, data.frame(group = "after_nonstem", wage = mean(after_nonstem$WAGP), hr_per_wk=mean(after_nonstem$WKHP), wk_per_yr=mean(after_nonstem$WKW), income_to_poverty=mean(after_nonstem$POVPIP,na.rm=TRUE), degree=mean(after_nonstem$SCHL)))
radardata$wage <- radardata$wage / 1000
radardata2 <- rbind(c(max(radardata$wage),max(radardata$hr_per_wk),max(radardata$wk_per_yr),max(radardata$income_to_poverty),max(radardata$degree)),
                    c(min(radardata$wage),min(radardata$hr_per_wk),min(radardata$wk_per_yr),min(radardata$income_to_poverty),min(radardata$degree)), 
                    radardata[,c(2:6)])
colors_border=c(rgb(0.2,0.5,0.5,0.9), rgb(0.8,0.2,0.5,0.9) , rgb(0.7,0.5,0.1,0.9), rgb(0.5,0.2,0.1,0.9) )
colors_in=c( rgb(0.2,0.5,0.5,0.4), rgb(0.8,0.2,0.5,0.4) , rgb(0.7,0.5,0.1,0.4), rgb(0.5,0.2,0.1,0.4) )
radarchart(radardata2 , axistype=1 , 
           # custom polygon
           pcol=colors_border , pfcol=colors_in , plwd=3 , plty=1,
           # custom the grid
           cglcol="grey", cglty=2, axislabcol="grey", 
           caxislabels = c('Min            ','','','','Max         '),
           cglwd=0.5
)
legend(x=0.9, y=1.4, legend = radardata[,1], bty = "n", pch=20 , col=colors_border , cex=0.9, pt.cex=1)
title("Changes in Working Conditions After STEM Policy Went Out ", cex.main=1)

(3) Class/Gender Structure of STEM Jobs

Now let’s study the class of work structure and gender structure in STEM/non-STEM jobs.

While the class of work structure of non-STEM jobs remains almost the same after STEM policy went out, we could tell the change of STEM jobs structure in the past decade. Compared to non-STEM group, less STEM jobs are of self-employed or for not-for-profit organizations. Instead, STEM people tend to stay at for-profit companies. This change could be relevant to both the change of the STEM industries and the thought conversion of STEM people. It’s likely that for these people, for-profit company is the option which allows better self-fulfillment.

# 3 cow, sex
cow <- data.frame(table(before_stem$COW))
cow <- cbind(cow,table(before_nonstem$COW))
cow <- cbind(cow,table(after_stem$COW))
cow <- cbind(cow,table(after_nonstem$COW))
cow <- cow[,c(1,2,4,6,8)]
names(cow) <- c('Class', 'before_stem',  'before_nonstem','after_stem','after_nonstem')
cow[,2] = cow[,2]/sum(cow[,2])
cow[,3] = cow[,3]/sum(cow[,3])
cow[,4] = cow[,4]/sum(cow[,4])
cow[,5] = cow[,5]/sum(cow[,5])
sex <- data.frame(table(before_stem$SEX))
sex <- cbind(sex,table(before_nonstem$SEX))
sex <- cbind(sex,table(after_stem$SEX))
sex <- cbind(sex,table(after_nonstem$SEX))
sex <- sex[,c(1,2,4,6,8)]
names(sex) <- c('Sex', 'before_stem',  'before_nonstem','after_stem','after_nonstem')
sex[,2] = sex[,2]/sum(sex[,2])
sex[,3] = sex[,3]/sum(sex[,3])
sex[,4] = sex[,4]/sum(sex[,4])
sex[,5] = sex[,5]/sum(sex[,5])
cow_melt = melt(cow, id.vars = c('Class'))
ggplot(cow_melt,aes(x = variable, y = value,fill = Class)) + 
  geom_bar(position = "fill",stat = "identity") + 
  theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
  ggtitle("Changes in Class of Work After STEM Policy Went Out") +
  theme(plot.title = element_text(size = rel(1),face="bold")) +
  xlab("") +
  ylab("Component Proportion")

If we try to address the gender proportion in jobs, we get some more interesting findings. First of all, the gender equality seems to be quite tenable in non-STEM jobs. However, when speaking of STEM jobs, the percentage of female employees dropped significantly after STEM policy went out. What could be the potential reasons? If it is relevant to STEM policy, does this mean that STEM policy is more appealing to male foreign students compared to female, and therefore more males come to US and stay? Yet, if we consider the fact that the proportion of non-US-born employees in the STEM jobs is actually not that big, we should realize that STEM policy could not be the major cause. In other words, there’re some other factors that are currently influencing the gender structure in STEM jobs, and we should pay attention to this huge gender gap.

colors_in1=c('rosybrown1', 'lightsteelblue2')
colors_in2=c('rosybrown3', 'lightsteelblue4')
colors_in3=c('tan1','seagreen1')
colors_in4=c('tan3','seagreen3')
colors_in=c('rosybrown1', 'lightsteelblue2','rosybrown3', 'lightsteelblue4')
pie(x=c(sex[1,2],sex[2,2]),labels=c(""),cex=1,radius=1,col=colors_in1)
par(new=TRUE)
pie(x=c(sex[1,3],sex[2,3]),labels=c(""), cex=0.8,radius=0.75,col=colors_in2)
par(new=TRUE)
pie(x=c(sex[1,4],sex[2,4]),labels=c(""),cex=1,radius=0.5,col=colors_in3)
par(new=TRUE)
pie(x=c(sex[1,5],sex[2,5]),labels=c(""),cex=0.8,radius=0.25,col=colors_in4)
legend(x=1.5, y=0.5, legend = c('',''), col = colors_in1, bty = "n", pch=20 ,cex=0.8, pt.cex=2)
legend(x=1.9, y=0.5, legend = c('',''), col = colors_in3, bty = "n", pch=20 ,cex=0.8, pt.cex=2)
text('2007', x=1.6, y=0.6,cex=0.8)
text('2014', x=2, y=0.6,cex=0.8)
text('female', x=1.2, y=0.4,cex=0.8)
text('male', x=1.2, y=0.25,cex=0.8)
legend(x=1.5,y=0.,legend=c('',''),col=c('white','grey'),bty = "n",  pch=20 ,cex=0.8, pt.cex=2)
legend(x=1.475,y=0.05,pt.cex=1.4, bty = "n", legend = c(""), pch = 21)
text('stem', x=1.2, y=-0.11,cex=0.8)
text('non-stem', x=1.25, y=-0.25,cex=0.8)
title("Changes in Gender Proportion of Jobs After STEM Policy Went Out",cex=0.8)

(4) Immigration Behaviors

If we assume the STEM policy does attract a lot of foreign students to come and study in US, does it mean that this policy will further influence them to stay in US permanently? To answer this question, we draw the following figure and we know the answer is NO. The figure generally presents the distribution of age of entry among immigrants to US. We can see from the plot that the proportion of immigrants who came to US during their age of schooling didn’t change much as the STEM policy being published, either for STEM or non-STEM people.

# 4 year of entry-stem/nonstem-before/after (for those who naturalized)
before_naturalize <- before_data[before_data$CIT == 4]
after_naturalize <- after_data[after_data$CIT == 4]
before_naturalize$AGEOFENTRY <- before_naturalize$YOEP - (2007 - before_naturalize$AGEP)
after_naturalize$AGEOFENTRY <- after_naturalize$YOEP - (2014 - after_naturalize$AGEP)
before_naturalize_stem <- before_naturalize[before_naturalize$SOCP == 'STEM']
before_naturalize_nonstem <- before_naturalize[before_naturalize$SOCP == 'NON-STEM']
after_naturalize_stem <- after_naturalize[after_naturalize$SOCP == 'STEM']
after_naturalize_nonstem <- after_naturalize[after_naturalize$SOCP == 'NON-STEM']
before_naturalize_age_stem <- cut(before_naturalize_stem$AGEOFENTRY, seq(0,100,length.out=21))
before_naturalize_age_stem <- data.frame(table(before_naturalize_age_stem))
before_naturalize_age_nonstem <- cut(before_naturalize_nonstem$AGEOFENTRY, seq(0,100,length.out=21))
before_naturalize_age_nonstem <- data.frame(table(before_naturalize_age_nonstem))
after_naturalize_age_stem <- cut(after_naturalize_stem$AGEOFENTRY, seq(0,100,length.out=21))
after_naturalize_age_stem <- data.frame(table(after_naturalize_age_stem))
after_naturalize_age_nonstem <- cut(after_naturalize_nonstem$AGEOFENTRY, seq(0,100,length.out=21))
after_naturalize_age_nonstem <- data.frame(table(after_naturalize_age_nonstem))
naturalized_age_stem <- merge(before_naturalize_age_stem,after_naturalize_age_stem, by.x="before_naturalize_age_stem", by.y='after_naturalize_age_stem')
names(naturalized_age_stem) <- c('age_range','before_stem','after_stem')
naturalized_age_stem$before_stem = naturalized_age_stem$before_stem/sum(naturalized_age_stem$before_stem)
naturalized_age_stem$after_stem = naturalized_age_stem$after_stem/sum(naturalized_age_stem$after_stem)
naturalized_age_nonstem <- merge(before_naturalize_age_nonstem,after_naturalize_age_nonstem, by.x="before_naturalize_age_nonstem", by.y='after_naturalize_age_nonstem')
names(naturalized_age_nonstem) <- c('age_range','before_nonstem','after_nonstem')
naturalized_age_nonstem$before_nonstem = naturalized_age_nonstem$before_nonstem/sum(naturalized_age_nonstem$before_nonstem)
naturalized_age_nonstem$after_nonstem = naturalized_age_nonstem$after_nonstem/sum(naturalized_age_nonstem$after_nonstem)
naturalized_age <- cbind(naturalized_age_stem,naturalized_age_nonstem)
naturalized_age <- naturalized_age[,c(1,2,5,3,6)]
naturalized_age <- melt(naturalized_age, id='age_range')
ggplot(data=naturalized_age,
       aes(x=age_range, y=value, col=variable, group=variable)) +
       geom_line()+
       theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
       ggtitle("Changes in Age of Entry Among Immigrants") +
       theme(plot.title = element_text(size = rel(1),face="bold")) +
       ylab("Proportion")

Summary

We know more about STEM after this project. We learn how STEM degrees relate to different industries and we have a basic understanding what our job will be like.

As graduating STEM degree students in NY, our career future is promising. In spite of NY and CA, some other states including Texas and Virginia also provide a good amount of job opening. Considering working conditions only, it’s a fair choice for us to further pursue a PhD degree.

However, the current gender disparity in STEM jobs is a question worth thinking about. The female proportion dropped from 47% to 25% and this is non-negligible.

Above is the project of our team. Thank you all for listening!

LS0tCnRpdGxlOiAiVGVhbSAjIDE1IFByb2plY3QgIyAxIFNURU0gYW5kIFVzIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCiMgSW50cm9kdWN0aW9uCgpJbiB0aGlzIHByb2plY3QsIHdlIGJhc2ljYWxseSBhbmFseXplIGhvdyBTVEVNIHBvbGljeSBpbmZsdWVuY2VzIHRoZSB3aG9sZSBBbWVyaWNhbiBTb2NpZXR5LCBpbmNsdWRpbmcgdGhlIGNpdGl6ZW5zIGFuZCB0aGUgbm9uLWNpdGl6ZW5zLiBUbyBtYWtlIHRoZSB0b3BpYyBtb3JlIHJldmVsZW50IHRvIG91cnNlbHZlcywgb3VyIGFuYWx5c2lzIGNvbnRhaW5zIHR3byBtYWluIHBhcnRzOiAoMSkgaG93IFNURU0gcG9saWN5IGluZmx1ZW5jZXMgZ3JhZHVhdGVkIHN0dWRlbnRzLCBhbmQgKDIpIGhvdyBTVEVNIHBvbGljeSBpbmZsdWVuY2VzIGVtcGxveW1lbnQgc2l0dWF0aW9uLiAKCkluIHBhcnQgKDEpLCB3ZSB1c2Ugc2V2ZXJhbCBkYXRhIHNldHMgdG8gdW5kZXJzdGFuZCBob3cgU1RFTSBkZWdyZWVzIGRldmVsb3AgaW50byBTVEVNIGpvYnMuIApJbiBwYXJ0ICgyKSwgd2UgdXNlIGRhdGEgc2V0cyBmcm9tIDIwMDcgYW5kIDIwMTQgdG8gY29tcGFyZSB0aGUgZW1wbG95bWVudCBzaXR1YXRpb25zIGFuZCB3b3JraW5nIGNvbmRpdGlvbnMgYmVmb3JlIGFuZCBhZnRlciB0aGUgYW5ub3VuY2VtZW50IG9mIHRoZSBTVEVNIHBvbGljeS4gCgpUZWFtIG1lbWJlcjogWWFxaW5nIFhpZQogICAgICAgICAgICAgUWluZyBZaW4KICAgICAgICAgICAgIFl1ZXFpIFpoYW5nCgojIFBhcnQgMS4gSW5mbHVlbmNlcyBvZiBTVEVNIHBvbGljeSBvbiBncmFkdWF0ZWQgc3R1ZGVudHMKCiMjIyAqKjEuIE91ciBPYmplY3RpdmUqKgoKSW4gdGhpcyBwYXJ0IG9mIGFuYWx5c2lzLCB3ZSB3YW50IHRvIGtub3cgaG93IFNURU0gcG9saWN5IGluZmx1ZW5jZSBncmFkdWF0ZWQgc3R1ZGVudHMuIFdlIGZpcnN0IHNlcGFyYXRlIG91ciBkYXRhIGludG8gMiBjYXRlZ29yaWVzOiBvbmUgY2F0ZWdvcnkgaW5jbHVkZXMgY2l0aXplbnMgYW5kIHRoZSBvdGhlciBjYXRlZ29yeSBpbmNsdWRlcyBub24tY2l0aXplbnMuIFRoZW4sIHdlIGZ1cnRoZXIgc2VwYXJhdGUgb3VyIGRhdGEgaW50byBTVEVNLW1ham9yIGRhdGEgYW5kIG5vbi1TVEVNLW1ham9yIGRhdGEuIEJ5IGRvaW5nIHRoZSBzZXBhcmF0aW9ucywgd2UgY2FuIGVhc2lseSBkbyBjb21wYXJpc29ucyBiZXR3ZWVuIGluZmx1ZW5jZXMgb2YgU1RFTSBwb2xpY3kgdG8gY2l0aXplbnMgYW5kIGluZmx1ZW5jZXMgb2YgU1RFTSBwb2xpY3kgdG8gbm9uLWNpdGl6ZW5zIGFuZCBiZXR3ZWVuIGVtcGxveW1lbnQgc3RhdHVzIG9mIFNURU0gbWFqb3JzIGFuZCBlbXBsb3ltZW50IHN0YXR1cyBvZiBub24tU1RFTSBtYWpvcnMuCgojIyMgKioyLiBPdXIgQ29uY2VybnMqKgoKMS4gSXMgaXQgdHJ1ZSB0aGF0IGdyYWR1YXRlZCBzdHVkZW50cyB3aXRoIFNURU0gZGVncmVlcyBjYW4gZWFzaWx5IGZpbmQgam9icz8KCjIuIERvIGxldmVscyBvZiBkZWdyZWVzIGluZmx1ZW5jZSBlbXBsb3ltZW50IHJhdGUgb2YgU1RFTSBzdHVkZW50cz8gRG8gbGV2ZWxzIG9mIGRlZ3JlZXMgaW5mbHVlbmNlIGVtcGxveW1lbnQgcmF0ZSBvZiBub24tU1RFTSBzdHVkZW50cz8KCjMuIFdoaWNoIGZpZWxkcyB3aWxsIFNURU0gZ3JhZHVhdGVkIHN0dWRlbnRzIGVudGVyIGFuZCB3aGljaCBmaWVsZHMgd2lsbCBub24tU1RFTSBncmFkdWF0ZWQgc3R1ZGVudHMgZW50ZXI/CgojIyMgKiozLiBPdXIgRmluZGluZ3MqKgoKQmVmb3JlIHdlIHN0YXJ0IHRvIGFuYWx5emUgZGF0YSwgd2Ugc2hvdWxkIGNsZWFuIGFuZCBwcmVwcm9jZXNzIGRhdGEuIEZvciBleGFtcGxlLCB3ZSBjYXRlZ29yaXplIHBlb3BsZSBhY2NvcmRpbmcgdG8gdGhlaXIgZGVncmVlIGZpZWxkIGFzIHN0ZW0gb3Igbm9uLXN0ZW0uCmBgYHtyfQpsaWJyYXJ5KGRhdGEudGFibGUpCmxpYnJhcnkoZHBseXIpCmNvbHM8LWMoIlNFUklBTE5PIiwiU1BPUkRFUiIsIlNUIiwiQUdFUCIsIkNJVCIsIk5XTEsiLCJTQ0giLCJTQ0hMIiwiV0tMIiwiV1JLIiwiRk9EMVAiLCJPQ0NQIikKZGF0YTE0YTwtZnJlYWQoIi9Vc2Vycy9ZYXFpbmdYaWUvRGVza3RvcC9BcHBsaWVkIERhdGEgU2NpZW5jZS9XZWVrMS9jc3ZfcHVzL3NzMTRwdXNhLmNzdiIsc2VsZWN0PWNvbHMpCmRhdGExNGI8LWZyZWFkKCIvVXNlcnMvWWFxaW5nWGllL0Rlc2t0b3AvQXBwbGllZCBEYXRhIFNjaWVuY2UvV2VlazEvY3N2X3B1cy9zczE0cHVzYi5jc3YiLHNlbGVjdD1jb2xzKQpkYXRhMTQ8LXJiaW5kKGRhdGExNGEsZGF0YTE0YikKZGF0YTE0PC1maWx0ZXIoZGF0YTE0LEZPRDFQIT0iTkEiKQpzdGVtPC1tYXRyaXgocmVwKDAsZGltKGRhdGExNClbMV0pLG5yb3c9ZGltKGRhdGExNClbMV0pCnN0ZW0uZmllbGQ8LWMoMTEwMywxMTA0LDExMDUsMTEwNiwxMzAxLDE0MDEsMjEwMCwyMTAxLDIxMDIsMjEwNSwyMTA2LDIxMDcsMjQwMCwyNDAxLDI0MDIsMjQwMywyNDA0LDI0MDcsMjQwOCwyNDA5LDI0MTAsMjQxMSwyNDEyLDI0MTMsMjQxNCwyNDE1LDI0MTYsMjQxNywyNDE4LDI0MTksMjQ5OSwyNTAwLDI1MDEsMjUwMiwyNTAzLDI1MDQsMjU5OSwzNjAwLDM2MDEsMzYwMiwzNjAzLDM2MDQsMzYwNSwzNjA2LDM2MDcsMzYwOCwzNjA5LDM2MTEsMzY5OSwzNzAwLDM3MDEsMzcwMiwzODAxLDQwMDIsNDAwNSw0MDA2LDUwMDAsNTAwMSw1MDAyLDUwMDMsNTAwNCw1MDA1LDUwMDYsNTAwNyw1MDA4LDUxMDIsNTIwNiw1OTAxLDYxMDUsNjIwMiw2MjEyKQpsPC1sZW5ndGgoc3RlbS5maWVsZCkKb3JkZXIuZm9kPC1jKCkKZm9yKGkgaW4gMTpsKQp7CiAgb3JkZXIuZm9kPC1jKG9yZGVyLmZvZCx3aGljaChkYXRhMTQkRk9EMVA9PXN0ZW0uZmllbGRbaV0pKQp9Cm9yZGVyLmZvZDwtc29ydChvcmRlci5mb2QpCnN0ZW1bb3JkZXIuZm9kXTwtMQpjb2xuYW1lcyhzdGVtKTwtIlNURU0iCmRhdGExNDwtY2JpbmQoZGF0YTE0LHN0ZW0pCmRhdGExNCRDSVRbd2hpY2goZGF0YTE0JENJVD09NSldPC0wCmRhdGExNCRDSVRbd2hpY2goZGF0YTE0JENJVD09NCldPC0xCmRhdGExNCRDSVRbd2hpY2goZGF0YTE0JENJVD09MyldPC0xCmRhdGExNCRDSVRbd2hpY2goZGF0YTE0JENJVD09MildPC0xCmRhdGExNDwtc3Vic2V0KGRhdGExNCxkYXRhMTQkU0NIPT0xKQpkYXRhMTQ8LWZpbHRlcihkYXRhMTQsZGF0YTE0JFNDSEw+MjApCmRhdGExNCRPQ0NQW3doaWNoKGRhdGExNCROV0xLPT0xKV08LSJOQSIKZGF0YTE0JE9DQ1Bbd2hpY2goZGF0YTE0JFdLTD09MildPC0iTkEiCmRhdGExNCRPQ0NQW3doaWNoKGRhdGExNCRXUks9PTIpXTwtIk5BIgpkYXRhMTQkT0NDUFt3aGljaChkYXRhMTQkT0NDUD09OTkyMCldPC0iTkEiCm9jY3AudHlwZTwtbWF0cml4KHJlcCgwLGRpbShkYXRhMTQpWzFdKSxucm93PWRpbShkYXRhMTQpWzFdKQpvY2NwLm1ncjwtYygwMDEwLDAwMjAsMDA0MCwwMDUwLDAwNjAsMDEwMCwwMTIwLDAxMzUsMDEzNiwwMTM3LDAxNDAsMDE1MCwwMTYwLDAyMDUsMDIyMCwwMjMwLDAzMDAsMDMxMCwwMzMwLDAzNDAsMDM1MCwwMzYwLDA0MTAsMDQyMCwwNDI1LDA0MzApCmZvcihpIGluIDE6bGVuZ3RoKG9jY3AubWdyKSkKewogIG9jY3AudHlwZVt3aGljaChkYXRhMTQkT0NDUD09b2NjcC5tZ3JbaV0pXTwtIk1HUiIKfQpvY2NwLmJ1czwtYygwNTAwLDA1MTAsMDUyMCwwNTMwLDA1NDAsMDU2NSwwNjAwLDA2MzAsMDY0MCwwNjUwLDA3MDAsMDcxMCwwNzI1LDA3MjYsMDczNSwwNzQwKQpmb3IoaSBpbiAxOmxlbmd0aChvY2NwLmJ1cykpCnsKICBvY2NwLnR5cGVbd2hpY2goZGF0YTE0JE9DQ1A9PW9jY3AuYnVzW2ldKV08LSJCVVMiCn0Kb2NjcC5maW48LWMoMDgwMCwwODEwLDA4MjAsMDgzMCwwODQwLDA4NTAsMDg2MCwwOTAwLDA5MTAsMDkzMCwwOTQwLDA5NTApCmZvcihpIGluIDE6bGVuZ3RoKG9jY3AuZmluKSkKewogIG9jY3AudHlwZVt3aGljaChkYXRhMTQkT0NDUD09b2NjcC5maW5baV0pXTwtIkZJTiIKfQpvY2NwLmNtbTwtYygxMDA1LDEwMDYsMTAwNywxMDEwLDEwMjAsMTAzMCwxMDUwLDEwNjAsMTEwNSwxMTA2LDExMDcsMTIwMCwxMjIwLDEyNDApCmZvcihpIGluIDE6bGVuZ3RoKG9jY3AuY21tKSkKewogIG9jY3AudHlwZVt3aGljaChkYXRhMTQkT0NDUD09b2NjcC5jbW1baV0pXTwtIkNNTSIKfQpvY2NwLmVuZzwtYygxMzAwLDEzMTAsMTMyMCwxMzQwLDEzNTAsMTM2MCwxNDAwLDE0MTAsMTQyMCwxNDMwLDE0NDAsMTQ1MCwxNDYwLDE1MjAsMTUzMCwxNTQwLDE1NTAsMTU2MCkKZm9yKGkgaW4gMTpsZW5ndGgob2NjcC5lbmcpKQp7CiAgb2NjcC50eXBlW3doaWNoKGRhdGExNCRPQ0NQPT1vY2NwLmVuZ1tpXSldPC0iRU5HIgp9Cm9jY3Auc2NpPC1jKDE2MDAsMTYxMCwxNjQwLDE2NTAsMTcwMCwxNzEwLDE3MjAsMTc0MCwxNzYwLDE4MDAsMTgyMCwxODQwLDE4NjAsMTkwMCwxOTEwLDE5MjAsMTkzMCwxOTY1KQpmb3IoaSBpbiAxOmxlbmd0aChvY2NwLnNjaSkpCnsKICBvY2NwLnR5cGVbd2hpY2goZGF0YTE0JE9DQ1A9PW9jY3Auc2NpW2ldKV08LSJTQ0kiCn0Kb2NjcC5jbXM8LWMoMjAwMCwyMDEwLDIwMTUsMjAxNiwyMDI1LDIwNDAsMjA1MCwyMDYwKQpmb3IoaSBpbiAxOmxlbmd0aChvY2NwLmNtcykpCnsKICBvY2NwLnR5cGVbd2hpY2goZGF0YTE0JE9DQ1A9PW9jY3AuY21zW2ldKV08LSJDTVMiCn0Kb2NjcC5sZ2w8LWMoMjEwMCwyMTA1LDIxNDUsMjE2MCkKZm9yKGkgaW4gMTpsZW5ndGgob2NjcC5sZ2wpKQp7CiAgb2NjcC50eXBlW3doaWNoKGRhdGExNCRPQ0NQPT1vY2NwLmxnbFtpXSldPC0iTEdMIgp9Cm9jY3AuZWR1PC1jKDIyMDAsMjMwMCwyMzEwLDIzMjAsMjMzMCwyMzQwLDI0NDAsMjU0MCwyNTUwKQpmb3IoaSBpbiAxOmxlbmd0aChvY2NwLmVkdSkpCnsKICBvY2NwLnR5cGVbd2hpY2goZGF0YTE0JE9DQ1A9PW9jY3AuZWR1W2ldKV08LSJFRFUiCn0Kb2NjcC5lbnQ8LWMoMjYwMCwyNjMwLDI3MDAsMjcxMCwyNzIwLDI3NDAsMjc1MCwyNzYwLDI4MDAsMjgxMCwyODI1LDI4MzAsMjg0MCwyODUwLDI4NjAsMjkwMCwyOTEwLDI5MjApCmZvcihpIGluIDE6bGVuZ3RoKG9jY3AuZW50KSkKewogIG9jY3AudHlwZVt3aGljaChkYXRhMTQkT0NDUD09b2NjcC5lbnRbaV0pXTwtIkVOVCIKfQpvY2NwLm1lZDwtYygzMDAwLDMwMTAsMzAzMCwzMDQwLDMwNTAsMzA2MCwzMTEwLDMxMjAsMzE0MCwzMTUwLDMxNjAsMzIwMCwzMjEwLDMyMjAsMzIzMCwzMjQ1LDMyNTAsMzI1NSwzMjU2LDMyNTgsMzI2MCwzMzAwLDMzMTAsMzMyMCwzNDAwLDM0MjAsMzUwMCwzNTEwLDM1MjAsMzUzNSwzNTQwKQpmb3IoaSBpbiAxOmxlbmd0aChvY2NwLm1lZCkpCnsKICBvY2NwLnR5cGVbd2hpY2goZGF0YTE0JE9DQ1A9PW9jY3AubWVkW2ldKV08LSJNRUQiCn0Kb2NjcC5obHM8LWMoMzYwMCwzNjEwLDM2MjAsMzYzMCwzNjQwLDM2NDUsMzY0NiwzNjQ3LDM2NDgsMzY0OSwzNjU1KQpmb3IoaSBpbiAxOmxlbmd0aChvY2NwLmhscykpCnsKICBvY2NwLnR5cGVbd2hpY2goZGF0YTE0JE9DQ1A9PW9jY3AuaGxzW2ldKV08LSJITFMiCn0Kb2NjcC5wcnQ8LWMoMzcwMCwzNzEwLDM3MjAsMzczMCwzNzQwLDM3NTAsMzgwMCwzODIwLDM4NDAsMzg1MCwzOTAwLDM5MTAsMzkzMCwzOTQwLDM5NDUsMzk1NSkKZm9yKGkgaW4gMTpsZW5ndGgob2NjcC5wcnQpKQp7CiAgb2NjcC50eXBlW3doaWNoKGRhdGExNCRPQ0NQPT1vY2NwLnBydFtpXSldPC0iUFJUIgp9Cm9jY3AuZWF0PC1jKDQwMDAsNDAxMCw0MDIwLDQwMzAsNDA0MCw0MDUwLDQwNjAsNDExMCw0MTIwLDQxMzAsNDE0MCw0MTUwKQpmb3IoaSBpbiAxOmxlbmd0aChvY2NwLmVhdCkpCnsKICBvY2NwLnR5cGVbd2hpY2goZGF0YTE0JE9DQ1A9PW9jY3AuZWF0W2ldKV08LSJFQVQiCn0Kb2NjcC5jbG48LWMoNDIwMCw0MjEwLDQyMjAsNDIzMCw0MjQwLDQyNTApCmZvcihpIGluIDE6bGVuZ3RoKG9jY3AuY2xuKSkKewogIG9jY3AudHlwZVt3aGljaChkYXRhMTQkT0NDUD09b2NjcC5jbG5baV0pXTwtIkNMTiIKfQpvY2NwLnByczwtYyg0MzAwLDQzMjAsNDM0MCw0MzUwLDQ0MDAsNDQxMCw0NDIwLDQ0MzAsNDQ2MCw0NDY1LDQ1MDAsNDUxMCw0NTIwLDQ1MzAsNDU0MCw0NjAwLDQ2MTAsNDYyMCw0NjQwLDQ2NTApCmZvcihpIGluIDE6bGVuZ3RoKG9jY3AucHJzKSkKewogIG9jY3AudHlwZVt3aGljaChkYXRhMTQkT0NDUD09b2NjcC5wcnNbaV0pXTwtIlBSUyIKfQpvY2NwLnNhbDwtYyg0NzAwLDQ3MTAsNDcyMCw0NzQwLDQ3NTAsNDc2MCw0ODAwLDQ4MTAsNDgyMCw0ODMwLDQ4NDAsNDg1MCw0OTAwLDQ5MjAsNDkzMCw0OTQwLDQ5NTAsNDk2NSkKZm9yKGkgaW4gMTpsZW5ndGgob2NjcC5zYWwpKQp7CiAgb2NjcC50eXBlW3doaWNoKGRhdGExNCRPQ0NQPT1vY2NwLnNhbFtpXSldPC0iU0FMIgp9Cm9jY3Aub2ZmPC1jKDUwMDAsNTAxMCw1MDIwLDUwMzAsNTEwMCw1MTEwLDUxMjAsNTEzMCw1MTQwLDUxNTAsNTE2MCw1MTY1LDUyMDAsNTIyMCw1MjMwLDUyNDAsNTI1MCw1MjYwLDUzMDAsNTMxMCw1MzIwLDUzMzAsNTM0MCw1MzUwLDUzNjAsNTQwMCw1NDEwLDU0MjAsNTUwMCw1NTEwLDU1MjAsNTUzMCw1NTQwLDU1NTAsNTU2MCw1NjAwLDU2MTAsNTYyMCw1NjMwLDU3MDAsNTgwMCw1ODEwLDU4MjAsNTg0MCw1ODUwLDU4NjAsNTkwMCw1OTEwLDU5MjAsNTk0MCkKZm9yKGkgaW4gMTpsZW5ndGgob2NjcC5vZmYpKQp7CiAgb2NjcC50eXBlW3doaWNoKGRhdGExNCRPQ0NQPT1vY2NwLm9mZltpXSldPC0iT0ZGIgp9Cm9jY3AuZmZmPC1jKDYwMDUsNjAxMCw2MDQwLDYwNTAsNjEwMCw2MTIwLDYxMzApCmZvcihpIGluIDE6bGVuZ3RoKG9jY3AuZmZmKSkKewogIG9jY3AudHlwZVt3aGljaChkYXRhMTQkT0NDUD09b2NjcC5mZmZbaV0pXTwtIkZGRiIKfQpvY2NwLmNvbjwtYyg2MjAwLDYyMTAsNjIyMCw2MjMwLDYyNDAsNjI1MCw2MjYwLDYzMDAsNjMyMCw2MzMwLDYzNTUsNjM2MCw2NDAwLDY0MjAsNjQ0MCw2NDYwLDY1MTUsNjUyMCw2NTMwLDY2MDAsNjY2MCw2NzAwLDY3MTAsNjcyMCw2NzMwLDY3NDAsNjc2NSkKZm9yKGkgaW4gMTpsZW5ndGgob2NjcC5jb24pKQp7CiAgb2NjcC50eXBlW3doaWNoKGRhdGExNCRPQ0NQPT1vY2NwLmNvbltpXSldPC0iQ09OIgp9Cm9jY3AuZXh0PC1jKDY4MDAsNjgyMCw2ODMwLDY4NDAsNjk0MCkKZm9yKGkgaW4gMTpsZW5ndGgob2NjcC5leHQpKQp7CiAgb2NjcC50eXBlW3doaWNoKGRhdGExNCRPQ0NQPT1vY2NwLmV4dFtpXSldPC0iRVhUIgp9Cm9jY3AucnByPC1jKDcwMDAsNzAxMCw3MDIwLDcwMzAsNzA0MCw3MTAwLDcxMTAsNzEyMCw3MTMwLDcxNDAsNzE1MCw3MTYwLDcyMDAsNzIxMCw3MjIwLDcyNDAsNzI2MCw3MzAwLDczMTUsNzMyMCw3MzMwLDczNDAsNzM1MCw3MzYwLDc0MTAsNzQyMCw3NDMwLDc1MTAsNzU0MCw3NTYwLDc2MTAsNzYzMCkKZm9yKGkgaW4gMTpsZW5ndGgob2NjcC5ycHIpKQp7CiAgb2NjcC50eXBlW3doaWNoKGRhdGExNCRPQ0NQPT1vY2NwLnJwcltpXSldPC0iUlBSIgp9Cm9jY3AucHJkPC1jKDc3MDAsNzcxMCw3NzIwLDc3MzAsNzc0MCw3NzUwLDc4MDAsNzgxMCw3ODMwLDc4NDAsNzg1MCw3ODU1LDc5MDAsNzkyMCw3OTMwLDc5NDAsNzk1MCw4MDMwLDgwNDAsODEwMCw4MTMwLDgxNDAsODIyMCw4MjUwLDgyNTUsODI1Niw4MzAwLDgzMTAsODMyMCw4MzMwLDgzNTAsODQwMCw4NDEwLDg0MjAsODQ1MCw4NDYwLDg1MDAsODUxMCw4NTMwLDg1NDAsODU1MCw4NjAwLDg2MTAsODYyMCw4NjMwLDg2NDAsODY1MCw4NzEwLDg3MjAsODczMCw4NzQwLDg3NTAsODc2MCw4ODAwLDg4MTAsODgzMCw4ODUwLDg5MTAsODkyMCw4OTMwLDg5NDAsODk1MCw4OTY1KQpmb3IoaSBpbiAxOmxlbmd0aChvY2NwLnByZCkpCnsKICBvY2NwLnR5cGVbd2hpY2goZGF0YTE0JE9DQ1A9PW9jY3AucHJkW2ldKV08LSJQUkQiCn0Kb2NjcC50cm48LWMoOTAwMCw5MDMwLDkwNDAsOTA1MCw5MTEwLDkxMjAsOTEzMCw5MTQwLDkxNTAsOTIwMCw5MjQwLDkyNjAsOTMwMCw5MzEwLDkzNTAsOTM2MCw5NDEwLDk0MTUsOTQyMCw5NTEwLDk1MjAsOTU2MCw5NjAwLDk2MTAsOTYyMCw5NjMwLDk2NDAsOTY1MCw5NzIwLDk3NTApCmZvcihpIGluIDE6bGVuZ3RoKG9jY3AudHJuKSkKewogIG9jY3AudHlwZVt3aGljaChkYXRhMTQkT0NDUD09b2NjcC50cm5baV0pXTwtIlRSTiIKfQpvY2NwLm1pbDwtYyg5ODAwLDk4MTAsOTgyMCw5ODMwLDk5MjApCmZvcihpIGluIDE6bGVuZ3RoKG9jY3AubWlsKSkKewogIG9jY3AudHlwZVt3aGljaChkYXRhMTQkT0NDUD09b2NjcC5taWxbaV0pXTwtIk1JTCIKfQpjb2xuYW1lcyhvY2NwLnR5cGUpPC0iT0NDUC5UWVBFIgpkYXRhMTQ8LWNiaW5kKGRhdGExNCxvY2NwLnR5cGUpCndyaXRlLmNzdihkYXRhMTQsZmlsZT0iZGF0YTIwMTQuY3N2Iixyb3cubmFtZXMgPSBGQUxTRSkKZGF0YS4xNDwtZnJlYWQoImRhdGEyMDE0LmNzdiIsc2VsZWN0PWMoIlNUIiwiQUdFUCIsIkNJVCIsIlNDSEwiLCJGT0QxUCIsIk9DQ1AiLCJTVEVNIiwiT0NDUC5UWVBFIikpCndyaXRlLmNzdihkYXRhLjE0LGZpbGU9ImZuZGF0YTIwMTQuY3N2Iixyb3cubmFtZXMgPSBGQUxTRSkKCmRhdGEuMTQubm9uY2l0PC1zdWJzZXQoZGF0YS4xNCxkYXRhLjE0JENJVD09MCkKZGF0YS4xNC5jaXQ8LXN1YnNldChkYXRhLjE0LGRhdGEuMTQkQ0lUIT0wKQp3cml0ZS5jc3YoZGF0YS4xNC5jaXQsZmlsZT0iZGF0YTIwMTRfY2l0LmNzdiIscm93Lm5hbWVzPUZBTFNFKQp3cml0ZS5jc3YoZGF0YS4xNC5ub25jaXQsZmlsZT0iZGF0YTIwMTRfbm9uY2l0LmNzdiIscm93Lm5hbWVzPUZBTFNFKQpgYGAKCgpXZSBhbHNvIHNlcGFyYXRlIGRhdGEgaW50byB0d28gcGFydHMgYWNjb3JkaW5nIHRvIHBlb3BsZSdzIGNpdGl6ZW5zaGlwIHN0YXR1cy4KYGBge3J9CnNldHdkKCIvVXNlcnMvWWFxaW5nWGllL0Rlc2t0b3AvQXBwbGllZCBEYXRhIFNjaWVuY2UvRmFsbDIwMTYtcHJvajEtZ3JwMTUvZGF0YSIpCnB1czExPC1yZWFkLmNzdigiZm5kYXRhMjAxMS5jc3YiKQpwdXMxMjwtcmVhZC5jc3YoImZuZGF0YTIwMTIuY3N2IikKcHVzMTM8LXJlYWQuY3N2KCJmbmRhdGEyMDEzLmNzdiIpCnB1czE0PC1yZWFkLmNzdigiZm5kYXRhMjAxNC5jc3YiKQoKcHVzMTFjaXQ8LXB1czExW3B1czExJENJVD09MSxdCnB1czExbmNpdDwtcHVzMTFbcHVzMTEkQ0lUPT0wLF0KcHVzMTJjaXQ8LXB1czEyW3B1czEyJENJVD09MSxdCnB1czEybmNpdDwtcHVzMTJbcHVzMTIkQ0lUPT0wLF0KcHVzMTNjaXQ8LXB1czEzW3B1czEzJENJVD09MSxdCnB1czEzbmNpdDwtcHVzMTNbcHVzMTMkQ0lUPT0wLF0KcHVzMTRjaXQ8LXB1czE0W3B1czE0JENJVD09MSxdCnB1czE0bmNpdDwtcHVzMTRbcHVzMTQkQ0lUPT0wLF0KYGBgCgoKQmVsb3cgc2hvd3MgdGhlIHN0cnVjdHVyZSBvZiBvdXIgcHJvY2Vzc2VkIGRhdGEuCmBgYHtyfQpsaWJyYXJ5KERUKQpkYXRhdGFibGUoaGVhZChwdXMxMWNpdCw1MCksb3B0aW9ucz1saXN0KHNjcm9sbFg9VCxwYWdlTGVuZ3RoPTEwKSkKYGBgCgojIyMjICgxKSBSYXRlIG9mIEVtcGxveW1lbnQKClRoZSBmaXJzdCBwbG90IHdlIG9idGFpbmVkIGV4cGxhaW5zIGhvdyB0aGUgcmF0ZSBvZiBlbXBsb3ltZW50IHZhcmllcyBhbW9uZyBjaXRpemVucyBvciBub24tY2l0aXplbnMgd2l0aCBzdGVtIG9yIG5vbi1zdGVtIGRlZ3JlZS4KYGBge3J9CiMgSW4gdGhpcyBwYXJ0LCBJIGFtIGdvaW5nIHRvIGNoZWNrIHRoZSA0LXllYXIgZW1wbG95bWVudCByYXRlcyBpbiBlYWNoIGNhdGVnb3J5LgojIEZpcnN0LCBJIHdpbGwgZWxpbWluYXRlIHRoZSByb3dzIHdpdGggYWdlIGdyZWF0ZXIgdGhhbiBvciBlcXVhbCB0byA2Ni4KcHVzMTFjaXRzdGVteTwtcHVzMTFjaXRbcHVzMTFjaXQkU1RFTT09MSZwdXMxMWNpdCRBR0VQPDY2LF0KcHVzMTFjaXRuc3RlbXk8LXB1czExY2l0W3B1czExY2l0JFNURU09PTAmcHVzMTFjaXQkQUdFUDw2NixdCnB1czExbmNpdHN0ZW15PC1wdXMxMW5jaXRbcHVzMTFuY2l0JFNURU09PTEmcHVzMTFuY2l0JEFHRVA8NjYsXQpwdXMxMW5jaXRuc3RlbXk8LXB1czExbmNpdFtwdXMxMW5jaXQkU1RFTT09MCZwdXMxMW5jaXQkQUdFUDw2NixdCnB1czEyY2l0c3RlbXk8LXB1czEyY2l0W3B1czEyY2l0JFNURU09PTEmcHVzMTJjaXQkQUdFUDw2NixdCnB1czEyY2l0bnN0ZW15PC1wdXMxMmNpdFtwdXMxMmNpdCRTVEVNPT0wJnB1czEyY2l0JEFHRVA8NjYsXQpwdXMxMm5jaXRzdGVteTwtcHVzMTJuY2l0W3B1czEybmNpdCRTVEVNPT0xJnB1czEybmNpdCRBR0VQPDY2LF0KcHVzMTJuY2l0bnN0ZW15PC1wdXMxMm5jaXRbcHVzMTJuY2l0JFNURU09PTAmcHVzMTJuY2l0JEFHRVA8NjYsXQpwdXMxM2NpdHN0ZW15PC1wdXMxM2NpdFtwdXMxM2NpdCRTVEVNPT0xJnB1czEzY2l0JEFHRVA8NjYsXQpwdXMxM2NpdG5zdGVteTwtcHVzMTNjaXRbcHVzMTNjaXQkU1RFTT09MCZwdXMxM2NpdCRBR0VQPDY2LF0KcHVzMTNuY2l0c3RlbXk8LXB1czEzbmNpdFtwdXMxM25jaXQkU1RFTT09MSZwdXMxM25jaXQkQUdFUDw2NixdCnB1czEzbmNpdG5zdGVteTwtcHVzMTNuY2l0W3B1czEzbmNpdCRTVEVNPT0wJnB1czEzbmNpdCRBR0VQPDY2LF0KcHVzMTRjaXRzdGVteTwtcHVzMTRjaXRbcHVzMTRjaXQkU1RFTT09MSZwdXMxNGNpdCRBR0VQPDY2LF0KcHVzMTRjaXRuc3RlbXk8LXB1czE0Y2l0W3B1czE0Y2l0JFNURU09PTAmcHVzMTRjaXQkQUdFUDw2NixdCnB1czE0bmNpdHN0ZW15PC1wdXMxNG5jaXRbcHVzMTRuY2l0JFNURU09PTEmcHVzMTRuY2l0JEFHRVA8NjYsXQpwdXMxNG5jaXRuc3RlbXk8LXB1czE0bmNpdFtwdXMxNG5jaXQkU1RFTT09MCZwdXMxNG5jaXQkQUdFUDw2NixdCgojIFRoZW4sIEkgd2lsbCBjYWxjdWxhdGUgdGhlIDQteWVhciBlbXBsb3ltZW50IHJhdGVzIGluIGVhY2ggY2F0ZWdvcnkuCmNpdHN0ZW1lbXA8LWMobnJvdyhwdXMxMWNpdHN0ZW15WyFpcy5uYShwdXMxMWNpdHN0ZW15JE9DQ1ApLF0pL25yb3cocHVzMTFjaXRzdGVteSksbnJvdyhwdXMxMmNpdHN0ZW15WyFpcy5uYShwdXMxMmNpdHN0ZW15JE9DQ1ApLF0pL25yb3cocHVzMTJjaXRzdGVteSksbnJvdyhwdXMxM2NpdHN0ZW15WyFpcy5uYShwdXMxM2NpdHN0ZW15JE9DQ1ApLF0pL25yb3cocHVzMTNjaXRzdGVteSksbnJvdyhwdXMxNGNpdHN0ZW15WyFpcy5uYShwdXMxNGNpdHN0ZW15JE9DQ1ApLF0pL25yb3cocHVzMTRjaXRzdGVteSkpCmNpdG5zdGVtZW1wPC1jKG5yb3cocHVzMTFjaXRuc3RlbXlbIWlzLm5hKHB1czExY2l0bnN0ZW15JE9DQ1ApLF0pL25yb3cocHVzMTFjaXRuc3RlbXkpLG5yb3cocHVzMTJjaXRuc3RlbXlbIWlzLm5hKHB1czEyY2l0bnN0ZW15JE9DQ1ApLF0pL25yb3cocHVzMTJjaXRuc3RlbXkpLG5yb3cocHVzMTNjaXRuc3RlbXlbIWlzLm5hKHB1czEzY2l0bnN0ZW15JE9DQ1ApLF0pL25yb3cocHVzMTNjaXRuc3RlbXkpLG5yb3cocHVzMTRjaXRuc3RlbXlbIWlzLm5hKHB1czE0Y2l0bnN0ZW15JE9DQ1ApLF0pL25yb3cocHVzMTRjaXRuc3RlbXkpKQpuY2l0c3RlbWVtcDwtYyhucm93KHB1czExbmNpdHN0ZW15WyFpcy5uYShwdXMxMW5jaXRzdGVteSRPQ0NQKSxdKS9ucm93KHB1czExbmNpdHN0ZW15KSxucm93KHB1czEybmNpdHN0ZW15WyFpcy5uYShwdXMxMm5jaXRzdGVteSRPQ0NQKSxdKS9ucm93KHB1czEybmNpdHN0ZW15KSxucm93KHB1czEzbmNpdHN0ZW15WyFpcy5uYShwdXMxM25jaXRzdGVteSRPQ0NQKSxdKS9ucm93KHB1czEzbmNpdHN0ZW15KSxucm93KHB1czE0bmNpdHN0ZW15WyFpcy5uYShwdXMxNG5jaXRzdGVteSRPQ0NQKSxdKS9ucm93KHB1czE0bmNpdHN0ZW15KSkKbmNpdG5zdGVtZW1wPC1jKG5yb3cocHVzMTFuY2l0bnN0ZW15WyFpcy5uYShwdXMxMW5jaXRuc3RlbXkkT0NDUCksXSkvbnJvdyhwdXMxMW5jaXRuc3RlbXkpLG5yb3cocHVzMTJuY2l0bnN0ZW15WyFpcy5uYShwdXMxMm5jaXRuc3RlbXkkT0NDUCksXSkvbnJvdyhwdXMxMm5jaXRuc3RlbXkpLG5yb3cocHVzMTNuY2l0bnN0ZW15WyFpcy5uYShwdXMxM25jaXRuc3RlbXkkT0NDUCksXSkvbnJvdyhwdXMxM25jaXRuc3RlbXkpLG5yb3cocHVzMTRuY2l0bnN0ZW15WyFpcy5uYShwdXMxNG5jaXRuc3RlbXkkT0NDUCksXSkvbnJvdyhwdXMxNG5jaXRuc3RlbXkpKQoKIyBGaW5hbGx5LCBJIHdpbGwgdmlzdWFsaXplIHRoZSA0LXllYXIgZW1wbG95bWVudCByYXRlcyBpbiBlYWNoIGNhdGVnb3J5LgplbXBtYXQ8LXJiaW5kKGNpdHN0ZW1lbXAsY2l0bnN0ZW1lbXAsbmNpdHN0ZW1lbXAsbmNpdG5zdGVtZW1wKQpjb2xuYW1lcyhlbXBtYXQpPC1jKCIyMDExIiwiMjAxMiIsIjIwMTMiLCIyMDE0IikKcm93bmFtZXMoZW1wbWF0KTwtYygiY2l0aXplbiBTVEVNIiwiY2l0aXplbiBub24tU1RFTSIsIm5vbi1jaXRpemVuIFNURU0iLCJub24tY2l0aXplbiBub24tU1RFTSIpCmVtcGRmPC1kYXRhLmZyYW1lKHllYXI9ZmFjdG9yKHJlcChjKCIyMDExIiwiMjAxMiIsIjIwMTMiLCIyMDE0IiksZWFjaD00KSxsZXZlbHM9YygiMjAxMSIsIjIwMTIiLCIyMDEzIiwiMjAxNCIpKSxzdGF0dXM9ZmFjdG9yKHJlcChjKCJjaXRpemVuIFNURU0iLCJjaXRpemVuIG5vbi1TVEVNIiwibm9uLWNpdGl6ZW4gU1RFTSIsIm5vbi1jaXRpemVuIG5vbi1TVEVNIiksNCkpLHJhdGU9YyhlbXBtYXRbLDFdLGVtcG1hdFssMl0sZW1wbWF0WywzXSxlbXBtYXRbLDRdKSkKbGlicmFyeShnZ3Bsb3QyKQpnZ3Bsb3QoZGF0YT1lbXBkZixhZXMoeD15ZWFyLHk9cmF0ZSxmaWxsPXN0YXR1cykpK2dlb21fYmFyKHN0YXQ9ImlkZW50aXR5Iixwb3NpdGlvbj1wb3NpdGlvbl9kb2RnZSgpKStnZW9tX3RleHQoYWVzKGxhYmVsPXJvdW5kKHJhdGUsMikpLHBvc2l0aW9uPXBvc2l0aW9uX2RvZGdlKHdpZHRoPTAuOSkpICsgZ2d0aXRsZSgiRW1wbG95bWVudCBSYXRlIG9mIERpZmZlcmVudCBEZWdyZWUvQ2l0aXplbnNoaXAgVHlwZSB2LnMuIFRpbWUiKSArIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IHJlbCgxKSxmYWNlPSJib2xkIikpCmBgYAoKRnJvbSB0aGUgcGxvdCB3ZSBjYW4gc2VlIHRoYXQgdGhlIHJhdGUgaXMgcXVpdGUgc3RhYmxlIGF0IGxlYXN0IGluIHJlY2VudCB5ZWFycywgYW5kIGluIGdlbmVyYWwgQ2l0aXplbnMgb3RoZXIgdGhhbiBub24tY2l0aXplbnMsIFNURU0gZGVncmVlcyBvdGhlciB0aGFuIG5vbi1TVEVNIGRlZ3JlZXMgYXJlIG1vcmUgZmF2b3JhYmxlIGluIGVtcGxveWVycycgZXllLgoKCk5vdyB3ZSBzdGFydCB0byB0aGluayBob3cgYWR2YW5jZWQgZGVncmVlIGluZmx1ZW5jZXMgdGhlIGVtcGxveW1lbnQgcmF0ZS4KRnJvbSB0aGUgZm9sbG93aW5nIGZpZ3VyZSwgd2Ugc2VlIGhvdyBpbXBvcnRhbnQgaXQgaXMgZm9yIG5vbi1jaXRpemVucyB0byBnZXQgYSBoaWdoZXIgZGVncmVlLCBzaW5jZSBmb3IgY2l0aXplbnMgd2l0aCBlaXRoZXIgU1RFTSBvciBub24tU1RFTSBkZWdyZWUsIHRoZSByYXRlIHN0YXlzIHNvbWV3aGF0IHN0YWJsZSBhbW9uZyBkaWZmZXJlbnQgZGVncmVlIGdyb3Vwcywgd2hpbGUgZm9yIG5vbi1jaXRpemVucywgdGhlIHJhdGUgY2FuIGNoYW5nZSBzaWduaWZpY2FudGx5LgpgYGB7cn0KIyBJbiB0aGlzIHBhcnQsIEkgYW0gZ29pbmcgdG8gY2FsY3VsYXRlIGVtcGxveW1lbnQgcmF0ZXMgb2YgZGlmZmVyZW50IGRlZ3JlZXMgaW4gZWFjaCBjYXRlZ29yeS4gVGhlIGRhdGEgc2V0IHRoYXQgSSB1c2UgaGVyZSBpcyB0aGUgMjAxNCBkYXRhIHNldC4KIyBGaXJzdCwgSSBzaG91bGQgZnVydGhlciBzZXBhcmF0ZSB0aGUgZGF0YSBzZXRzIHVzaW5nIHRoZSB2YXJpYWJsZSBTQ0hMIChkZWdyZWUgbGV2ZWwpLgpwdXMxNGNpdHN0ZW15YjwtcHVzMTRjaXRzdGVteVtwdXMxNGNpdHN0ZW15JFNDSEw9PTIxLF0KcHVzMTRjaXRzdGVteW08LXB1czE0Y2l0c3RlbXlbcHVzMTRjaXRzdGVteSRTQ0hMPT0yMixdCnB1czE0Y2l0c3RlbXlwPC1wdXMxNGNpdHN0ZW15W3B1czE0Y2l0c3RlbXkkU0NITD09MjMsXQpwdXMxNGNpdHN0ZW15ZDwtcHVzMTRjaXRzdGVteVtwdXMxNGNpdHN0ZW15JFNDSEw9PTI0LF0KcHVzMTRjaXRuc3RlbXliPC1wdXMxNGNpdG5zdGVteVtwdXMxNGNpdG5zdGVteSRTQ0hMPT0yMSxdCnB1czE0Y2l0bnN0ZW15bTwtcHVzMTRjaXRuc3RlbXlbcHVzMTRjaXRuc3RlbXkkU0NITD09MjIsXQpwdXMxNGNpdG5zdGVteXA8LXB1czE0Y2l0bnN0ZW15W3B1czE0Y2l0bnN0ZW15JFNDSEw9PTIzLF0KcHVzMTRjaXRuc3RlbXlkPC1wdXMxNGNpdG5zdGVteVtwdXMxNGNpdG5zdGVteSRTQ0hMPT0yNCxdCnB1czE0bmNpdHN0ZW15YjwtcHVzMTRuY2l0c3RlbXlbcHVzMTRuY2l0c3RlbXkkU0NITD09MjEsXQpwdXMxNG5jaXRzdGVteW08LXB1czE0bmNpdHN0ZW15W3B1czE0bmNpdHN0ZW15JFNDSEw9PTIyLF0KcHVzMTRuY2l0c3RlbXlwPC1wdXMxNG5jaXRzdGVteVtwdXMxNG5jaXRzdGVteSRTQ0hMPT0yMyxdCnB1czE0bmNpdHN0ZW15ZDwtcHVzMTRuY2l0c3RlbXlbcHVzMTRuY2l0c3RlbXkkU0NITD09MjQsXQpwdXMxNG5jaXRuc3RlbXliPC1wdXMxNG5jaXRuc3RlbXlbcHVzMTRuY2l0bnN0ZW15JFNDSEw9PTIxLF0KcHVzMTRuY2l0bnN0ZW15bTwtcHVzMTRuY2l0bnN0ZW15W3B1czE0bmNpdG5zdGVteSRTQ0hMPT0yMixdCnB1czE0bmNpdG5zdGVteXA8LXB1czE0bmNpdG5zdGVteVtwdXMxNG5jaXRuc3RlbXkkU0NITD09MjMsXQpwdXMxNG5jaXRuc3RlbXlkPC1wdXMxNG5jaXRuc3RlbXlbcHVzMTRuY2l0bnN0ZW15JFNDSEw9PTI0LF0KCiMgVGhlbiwgSSB3aWxsIGNhbGN1bGF0ZSBlbXBsb3ltZW50IHJhdGVzIG9mIGRpZmZlcmVudCBkZWdyZWVzIGluIGVhY2ggY2F0ZWdvcnkuCmNpdHN0ZW1kZWc8LWMobnJvdyhwdXMxNGNpdHN0ZW15YlshaXMubmEocHVzMTRjaXRzdGVteWIkT0NDUCksXSkvbnJvdyhwdXMxNGNpdHN0ZW15YiksbnJvdyhwdXMxNGNpdHN0ZW15bVshaXMubmEocHVzMTRjaXRzdGVteW0kT0NDUCksXSkvbnJvdyhwdXMxNGNpdHN0ZW15bSksbnJvdyhwdXMxNGNpdHN0ZW15cFshaXMubmEocHVzMTRjaXRzdGVteXAkT0NDUCksXSkvbnJvdyhwdXMxNGNpdHN0ZW15cCksbnJvdyhwdXMxNGNpdHN0ZW15ZFshaXMubmEocHVzMTRjaXRzdGVteWQkT0NDUCksXSkvbnJvdyhwdXMxNGNpdHN0ZW15ZCkpCmNpdG5zdGVtZGVnPC1jKG5yb3cocHVzMTRjaXRuc3RlbXliWyFpcy5uYShwdXMxNGNpdG5zdGVteWIkT0NDUCksXSkvbnJvdyhwdXMxNGNpdG5zdGVteWIpLG5yb3cocHVzMTRjaXRuc3RlbXltWyFpcy5uYShwdXMxNGNpdG5zdGVteW0kT0NDUCksXSkvbnJvdyhwdXMxNGNpdG5zdGVteW0pLG5yb3cocHVzMTRjaXRuc3RlbXlwWyFpcy5uYShwdXMxNGNpdG5zdGVteXAkT0NDUCksXSkvbnJvdyhwdXMxNGNpdG5zdGVteXApLG5yb3cocHVzMTRjaXRuc3RlbXlkWyFpcy5uYShwdXMxNGNpdG5zdGVteWQkT0NDUCksXSkvbnJvdyhwdXMxNGNpdG5zdGVteWQpKQpuY2l0c3RlbWRlZzwtYyhucm93KHB1czE0bmNpdHN0ZW15YlshaXMubmEocHVzMTRuY2l0c3RlbXliJE9DQ1ApLF0pL25yb3cocHVzMTRuY2l0c3RlbXliKSxucm93KHB1czE0bmNpdHN0ZW15bVshaXMubmEocHVzMTRuY2l0c3RlbXltJE9DQ1ApLF0pL25yb3cocHVzMTRuY2l0c3RlbXltKSxucm93KHB1czE0bmNpdHN0ZW15cFshaXMubmEocHVzMTRuY2l0c3RlbXlwJE9DQ1ApLF0pL25yb3cocHVzMTRuY2l0c3RlbXlwKSxucm93KHB1czE0bmNpdHN0ZW15ZFshaXMubmEocHVzMTRuY2l0c3RlbXlkJE9DQ1ApLF0pL25yb3cocHVzMTRuY2l0c3RlbXlkKSkKbmNpdG5zdGVtZGVnPC1jKG5yb3cocHVzMTRuY2l0bnN0ZW15YlshaXMubmEocHVzMTRuY2l0bnN0ZW15YiRPQ0NQKSxdKS9ucm93KHB1czE0bmNpdG5zdGVteWIpLG5yb3cocHVzMTRuY2l0bnN0ZW15bVshaXMubmEocHVzMTRuY2l0bnN0ZW15bSRPQ0NQKSxdKS9ucm93KHB1czE0bmNpdG5zdGVteW0pLG5yb3cocHVzMTRuY2l0bnN0ZW15cFshaXMubmEocHVzMTRuY2l0bnN0ZW15cCRPQ0NQKSxdKS9ucm93KHB1czE0bmNpdG5zdGVteXApLG5yb3cocHVzMTRuY2l0bnN0ZW15ZFshaXMubmEocHVzMTRuY2l0bnN0ZW15ZCRPQ0NQKSxdKS9ucm93KHB1czE0bmNpdG5zdGVteWQpKQoKIyBGaW5hbGx5LCBJIHdpbGwgdmlzdWFsaXplIGVtcGxveW1lbnQgcmF0ZXMgb2YgZGlmZmVyZW50IGRlZ3JlZXMgaW4gZWFjaCBjYXRlZ29yeS4KZGVnbWF0PC1yYmluZChjaXRzdGVtZGVnLGNpdG5zdGVtZGVnLG5jaXRzdGVtZGVnLG5jaXRuc3RlbWRlZykKY29sbmFtZXMoZGVnbWF0KTwtYygiYmFjaGVsb3IiLCJtYXN0ZXIiLCJwcm9mZXNzaW9uYWwiLCJkb2N0b3JhdGUiKQpyb3duYW1lcyhkZWdtYXQpPC1jKCJjaXRpemVuIFNURU0iLCJjaXRpemVuIG5vbi1TVEVNIiwibm9uLWNpdGl6ZW4gU1RFTSIsIm5vbi1jaXRpemVuIG5vbi1TVEVNIikKZGVnZGY8LWRhdGEuZnJhbWUoZGVncmVlPWZhY3RvcihyZXAoYygiYmFjaGVsb3IiLCJtYXN0ZXIiLCJwcm9mZXNzaW9uYWwiLCJkb2N0b3JhdGUiKSxlYWNoPTQpLGxldmVscz1jKCJiYWNoZWxvciIsIm1hc3RlciIsInByb2Zlc3Npb25hbCIsImRvY3RvcmF0ZSIpKSxzdGF0dXM9ZmFjdG9yKHJlcChjKCJjaXRpemVuIFNURU0iLCJjaXRpemVuIG5vbi1TVEVNIiwibm9uLWNpdGl6ZW4gU1RFTSIsIm5vbi1jaXRpemVuIG5vbi1TVEVNIiksNCkpLHJhdGU9YyhkZWdtYXRbLDFdLGRlZ21hdFssMl0sZGVnbWF0WywzXSxkZWdtYXRbLDRdKSkKZ2dwbG90KGRhdGE9ZGVnZGYsYWVzKHg9ZGVncmVlLHk9cmF0ZSxmaWxsPXN0YXR1cykpK2dlb21fYmFyKHN0YXQ9ImlkZW50aXR5Iixwb3NpdGlvbj1wb3NpdGlvbl9kb2RnZSgpKStnZW9tX3RleHQoYWVzKGxhYmVsPXJvdW5kKHJhdGUsMikpLHBvc2l0aW9uPXBvc2l0aW9uX2RvZGdlKHdpZHRoPTAuOSkpK2dndGl0bGUoIkVtcGxveW1lbnQgUmF0ZSB2LnMuIERlZ3JlZS9DaXRpemVuc2hpcCBUeXBlIikgKwogICAgICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gcmVsKDEpLGZhY2U9ImJvbGQiKSkKYGBgCgojIyMjICgyKSBTVEVNIGRlZ3JlZXMgYW5kIFNURU0gam9icwoKTm93IHdlIHdhbnQgdG8gaGF2ZSBhIGNsb3NlciBsb29rIGF0IGhvdyBTVEVNIGRlZ3JlZXMgZGV2ZWxvcCBpbnRvIFNURU0gam9icy4KRnJvbSB0aGVzZSBzYW5rZXkgcGxvdHMsIHdlIHNlZSB0aGUgY29tcG9uZW50IG9mIFNURU0gZGVncmVlcyBhbmQgaG93IFNURU0gZGVncmVlIHBlb3BsZSBzZXBhcmF0ZSBpbnRvIGRpZmZlcmVudCBpbmR1c3RyaWVzIGFmdGVyIGdyYWR1YXRpb24gZm9yIGJvdGggY2l0aXplbnMgYW5kIG5vbi1jaXRpemVucy4gRmlyc3QsIGFwcGFyYW50bHksIG1vcmUgcGVvcGxlIHB1cnN1ZSBhIG5vbi1TVEVNIGRlZ3JlZS4gSW4gU1RFTSBkZWdyZWVzLCBhcyBmb3IgcG9wdWxhcml0eSwgYmlvbG9neSBvdXRwZXJmb3JtcyBib3RoIENTIGFuZCBFRSBhbW9uZyBjaXRpemVucyB3aGlsZSBpdCdzIHRoZSBvcHBvc2l0ZSBhbW9uZyBub24tY2l0aXplbnMuIFRoaXMgaXMgcXVpdGUgcmVhc29uYWJsZSBzaW5jZSBmb3JlaWduIHN0dWRlbnRzIG5lZWQgdG8gY29uc2lkZXIgbW9yZSBhYm91dCBnZXR0aW5nIGEgam9iLiBGb3IgYm90aCBTVEVNIGFuZCBub24tU1RFTSBkZWdyZWUgZ3JvdXBzLCB0aGUgaW5kdXN0cnkgdGhleSBjaG9vc2UgYWZ0ZXIgZ3JhZHVhdGlvbiB2YXJpZXMgYSBsb3QuCmBgYHtyfQojIEluIG9yZGVyIHRvIGdldCB0b3AgbWFqb3JzIGluIGJvdGggc3RlbSBmaWVsZHMgYW5kIG5vbi1zdGVtIGZpZWxkcywgSSBuZWVkIHRvIG9idGFpbiB0aGUgZnJlcXVlbmN5IG9mIGVhY2ggbWFqb3IgaW4gZWFjaCBkYXRhIHNldCBhbmQgc29ydCBtYWpvcnMgYnkgZnJlcXVlbmNpZXMgZm9yIGVhY2ggZGF0YSBzZXQuCnRvcG1ham9yczE0Y2l0PC1hcy5kYXRhLmZyYW1lKHNvcnQodGFibGUocHVzMTRjaXQkRk9EMVApLGRlY3JlYXNpbmc9VCkpCnRvcG1ham9yczE0bmNpdDwtYXMuZGF0YS5mcmFtZShzb3J0KHRhYmxlKHB1czE0bmNpdCRGT0QxUCksZGVjcmVhc2luZz1UKSkKY29sbmFtZXModG9wbWFqb3JzMTRjaXQpPC0iZnJlcXVlbmN5Igpjb2xuYW1lcyh0b3BtYWpvcnMxNG5jaXQpPC0iZnJlcXVlbmN5IgoKIyBOb3csIEkgZ2VuZXJhdGUgc3RlbS9ub24tc3RlbSB2ZWN0b3JzIGZvciBtYWpvciB2ZWN0b3JzLgptYWpvcnN0ZW12MTRjaXQ8LXZlY3RvcigpCm1ham9yc3RlbXYxNG5jaXQ8LXZlY3RvcigpCmZvcihpIGluIDE6bnJvdyh0b3BtYWpvcnMxNGNpdCkpewogIG1ham9yc3RlbXYxNGNpdFtpXTwtKHB1czE0Y2l0W3B1czE0Y2l0JEZPRDFQPT1hcy5udW1lcmljKHJvd25hbWVzKHRvcG1ham9yczE0Y2l0KVtpXSksd2hpY2goY29sbmFtZXMocHVzMTRjaXQpPT0iU1RFTSIpXSlbMV0KfQpmb3IoaSBpbiAxOm5yb3codG9wbWFqb3JzMTRuY2l0KSl7CiAgbWFqb3JzdGVtdjE0bmNpdFtpXTwtKHB1czE0bmNpdFtwdXMxNG5jaXQkRk9EMVA9PWFzLm51bWVyaWMocm93bmFtZXModG9wbWFqb3JzMTRuY2l0KVtpXSksd2hpY2goY29sbmFtZXMocHVzMTRuY2l0KT09IlNURU0iKV0pWzFdCn0KCiMgV2UgbmVlZCB0byBnZW5lcmF0ZSBtYWpvciB2cyBzdGVtIG1hdHJpeCBub3cuCmxpYnJhcnkoZHBseXIpCm1zMTRjaXQ8LXRvcG1ham9yczE0Y2l0JT4lbXV0YXRlKG1ham9yPXJvd25hbWVzKHRvcG1ham9yczE0Y2l0KSkKbXMxNGNpdDwtbXMxNGNpdCU+JW11dGF0ZShzdGVtPW1ham9yc3RlbXYxNGNpdCkKbXMxNGNpdDwtbXMxNGNpdCU+JW11dGF0ZShwcm9wb3J0aW9uPWZyZXF1ZW5jeS9zdW0oZnJlcXVlbmN5KSkKCm1zMTRuY2l0PC10b3BtYWpvcnMxNG5jaXQlPiVtdXRhdGUobWFqb3I9cm93bmFtZXModG9wbWFqb3JzMTRuY2l0KSkKbXMxNG5jaXQ8LW1zMTRuY2l0JT4lbXV0YXRlKHN0ZW09bWFqb3JzdGVtdjE0bmNpdCkKbXMxNG5jaXQ8LW1zMTRuY2l0JT4lbXV0YXRlKHByb3BvcnRpb249ZnJlcXVlbmN5L3N1bShmcmVxdWVuY3kpKQoKIyBOb3csIEkgd2lsbCBwcmVwcm9jZXNzIGRhdGEgZm9yIFNhbmtleSBwbG90LgptczE0Y2l0YWxsbnM8LW1zMTRjaXQlPiVmaWx0ZXIoc3RlbT09MCkKbXMxNGNpdGFsbHM8LW1zMTRjaXQlPiVmaWx0ZXIoc3RlbT09MSkKbXMxNGNpdHRvcG5zPC1yYmluZChtczE0Y2l0YWxsbnNbMToyMCxdLGMoc3VtKG1zMTRjaXRhbGxuc1stKDE6MjApLDFdKSwib3RoZXIiLDAsc3VtKG1zMTRjaXRhbGxuc1stKDE6MjApLDRdKSkpCm1zMTRjaXR0b3BzPC1yYmluZChtczE0Y2l0YWxsc1sxOjIwLF0sYyhzdW0obXMxNGNpdGFsbHNbLSgxOjIwKSwxXSksIm90aGVyIiwxLHN1bShtczE0Y2l0YWxsc1stKDE6MjApLDRdKSkpCm1zMTRjaXR0b3A8LXJiaW5kKG1zMTRjaXR0b3BzLG1zMTRjaXR0b3BucykKCm1zMTRuY2l0YWxsbnM8LW1zMTRuY2l0JT4lZmlsdGVyKHN0ZW09PTApCm1zMTRuY2l0YWxsczwtbXMxNG5jaXQlPiVmaWx0ZXIoc3RlbT09MSkKbXMxNG5jaXR0b3BuczwtcmJpbmQobXMxNG5jaXRhbGxuc1sxOjIwLF0sYyhzdW0obXMxNG5jaXRhbGxuc1stKDE6MjApLDFdKSwib3RoZXIiLDAsc3VtKG1zMTRuY2l0YWxsbnNbLSgxOjIwKSw0XSkpKQptczE0bmNpdHRvcHM8LXJiaW5kKG1zMTRuY2l0YWxsc1sxOjIwLF0sYyhzdW0obXMxNG5jaXRhbGxzWy0oMToyMCksMV0pLCJvdGhlciIsMSxzdW0obXMxNG5jaXRhbGxzWy0oMToyMCksNF0pKSkKbXMxNG5jaXR0b3A8LXJiaW5kKG1zMTRuY2l0dG9wcyxtczE0bmNpdHRvcG5zKQoKIyBUaGUgZm9sbG93aW5nIGZ1bmN0aW9uIGlzIHVzZWQgdG8gdHJhbnNmZXIgbWFqb3IgY29kZXMgaW50byBtYWpvciBuYW1lcwpjb2RlbmFtZTwtZnVuY3Rpb24oY29kZSl7CiAgbmFtZTwtIm90aGVyIgogIGlmKGNvZGU9PTExMDApIG5hbWU8LSJnZW5lcmFsIGFncmljdWx0dXJlIgogIGlmKGNvZGU9PTExMDEpIG5hbWU8LSJhZ3JpY3VsdHVyZSBwcm9kdWN0aW9uIGFuZCBtYW5hZ2VtZW50IgogIGlmKGNvZGU9PTExMDIpIG5hbWU8LSJhZ3JpY3VsdHVyYWwgZWNvbm9taWNzIgogIGlmKGNvZGU9PTExMDMpIG5hbWU8LSJhbmltYWwgc2NpZW5jZXMiCiAgaWYoY29kZT09MTEwNCkgbmFtZTwtImZvb2Qgc2NpZW5jZSIKICBpZihjb2RlPT0xMTA1KSBuYW1lPC0icGxhbnQgc2NpZW5jZSBhbmQgYWdyb25vbXkiCiAgaWYoY29kZT09MTEwNikgbmFtZTwtInNvaWwgc2NpZW5jZSIKICBpZihjb2RlPT0xMTk5KSBuYW1lPC0ibWlzY2VsbGFuZW91cyBhZ3JpY3VsdHVyZSIKICBpZihjb2RlPT0xMzAxKSBuYW1lPC0iZW52aXJvbm1lbnRhbCBzY2llbmNlIgogIGlmKGNvZGU9PTEzMDIpIG5hbWU8LSJmb3Jlc3RyeSIKICBpZihjb2RlPT0xMzAzKSBuYW1lPC0ibmF0dXJhbCByZXNvdXJjZXMgbWFuYWdlbWVudCIKICBpZihjb2RlPT0xNDAxKSBuYW1lPC0iYXJjaGl0ZWN0dXJlIgogIGlmKGNvZGU9PTE1MDEpIG5hbWU8LSJhcmVhIGV0aG5pYyBhbmQgY2l2aWxpemF0aW9uIgogIGlmKGNvZGU9PTE5MDEpIG5hbWU8LSJjb21tdW5pY2F0aW9ucyIKICBpZihjb2RlPT0xOTAyKSBuYW1lPC0iam91cm5hbGlzbSIKICBpZihjb2RlPT0xOTAzKSBuYW1lPC0ibWFzcyBtZWRpYSIKICBpZihjb2RlPT0xOTA0KSBuYW1lPC0iYWR2ZXJ0aXNpbmcgYW5kIHB1YmxpYyByZWxhdGlvbnMiCiAgaWYoY29kZT09MjAwMSkgbmFtZTwtImNvbW11bmljYXRpb24gdGVjaG5vbG9naWVzIgogIGlmKGNvZGU9PTIxMDApIG5hbWU8LSJjb21wdXRlciBhbmQgaW5mb3JtYXRpb24gc3lzdGVtcyIKICBpZihjb2RlPT0yMTAxKSBuYW1lPC0iY29tcHV0ZXIgcHJvZ3JhbW1pbmcgYW5kIGRhdGEgcHJvY2Vzc2luZyIKICBpZihjb2RlPT0yMTAyKSBuYW1lPC0iY29tcHV0ZXIgc2NpZW5jZSIKICBpZihjb2RlPT0yMTA1KSBuYW1lPC0iaW5mb3JtYXRpb24gc2NpZW5jZXMiCiAgaWYoY29kZT09MjEwNikgbmFtZTwtImNvbXB1dGVyIGFkbWluaXN0cmF0aW9uIG1hbmFnZW1lbnQgYW5kIHNlY3VyaXR5IgogIGlmKGNvZGU9PTIxMDcpIG5hbWU8LSJjb21wdXRlciBuZXR3b3JraW5nIGFuZCB0ZWxlY29tbXVuaWNhdGlvbnMiCiAgaWYoY29kZT09MjIwMSkgbmFtZTwtImNvc21ldG9sb2d5IHNlcnZpY2VzIGFuZCBjdWxpbmFyeSBhcnRzIgogIGlmKGNvZGU9PTIzMDApIG5hbWU8LSJnZW5lcmFsIGVkdWNhdGlvbiIKICBpZihjb2RlPT0yMzAxKSBuYW1lPC0iZWR1Y2F0aW9uYWwgYWRtaW5pc3RyYXRpb24gYW5kIHN1cGVydmlzaW9uIgogIGlmKGNvZGU9PTIzMDMpIG5hbWU8LSJzY2hvb2wgc3R1ZGVudCBjb3Vuc2VsaW5nIgogIGlmKGNvZGU9PTIzMDQpIG5hbWU8LSJlbGVtZW50YXJ5IGVkdWNhdGlvbiIKICBpZihjb2RlPT0yMzA1KSBuYW1lPC0ibWF0aGVtYXRpY3MgdGVhY2hlciBlZHVjYXRpb24iCiAgaWYoY29kZT09MjMwNikgbmFtZTwtInBoeXNpY2FsIGFuZCBoZWFsdGggZWR1Y2F0aW9uIHRlYWNoaW5nIgogIGlmKGNvZGU9PTIzMDcpIG5hbWU8LSJlYXJseSBjaGlsZGhvb2QgZWR1Y2F0aW9uIgogIGlmKGNvZGU9PTIzMDgpIG5hbWU8LSJzY2llbmNlIGFuZCBjb21wdXRlciB0ZWFjaGVyIGVkdWNhdGlvbiIKICBpZihjb2RlPT0yMzA5KSBuYW1lPC0ic2Vjb25kYXJ5IHRlYWNoZXIgZWR1Y2F0aW9uIgogIGlmKGNvZGU9PTIzMTApIG5hbWU8LSJzcGVjaWFsIG5lZWRzIGVkdWNhdGlvbiIKICBpZihjb2RlPT0yMzExKSBuYW1lPC0ic29jaWFsIHNjaWVuY2Ugb3IgaGlzdG9yeSB0ZWFjaGVyIGVkdWNhdGlvbiIKICBpZihjb2RlPT0yMzEyKSBuYW1lPC0idGVhY2hlciBlZHVjYXRpb246IG11bHRpcGxlIGxldmVscyIKICBpZihjb2RlPT0yMzEzKSBuYW1lPC0ibGFuZ3VhZ2UgYW5kIGRyYW1hIGVkdWNhdGlvbiIKICBpZihjb2RlPT0yMzE0KSBuYW1lPC0iYXJ0IGFuZCBtdXNpYyBlZHVjYXRpb24iCiAgaWYoY29kZT09MjM5OSkgbmFtZTwtIm1pc2NlbGxhbmVvdXMgZWR1Y2F0aW9uIgogIGlmKGNvZGU9PTI0MDApIG5hbWU8LSJnZW5lcmFsIGVuZ2luZWVyaW5nIgogIGlmKGNvZGU9PTI0MDEpIG5hbWU8LSJhZXJvc3BhY2UgZW5naW5lZXJpbmciCiAgaWYoY29kZT09MjQwMikgbmFtZTwtImJpb2xvZ2ljYWwgZW5naW5lZXJpbmciCiAgaWYoY29kZT09MjQwMykgbmFtZTwtImFyY2hpdGVjdHVyYWwgZW5naW5lZXJpbmciCiAgaWYoY29kZT09MjQwNCkgbmFtZTwtImJpb21lZGljYWwgZW5naW5lZXJpbmciCiAgaWYoY29kZT09MjQwNSkgbmFtZTwtImNoZW1pY2FsIGVuZ2luZWVyaW5nIgogIGlmKGNvZGU9PTI0MDYpIG5hbWU8LSJjaXZpbCBlbmdpbmVlcmluZyIKICBpZihjb2RlPT0yNDA3KSBuYW1lPC0iY29tcHV0ZXIgZW5naW5lZXJpbmciCiAgaWYoY29kZT09MjQwOCkgbmFtZTwtImVsZWN0cmljYWwgZW5naW5lZXJpbmciCiAgaWYoY29kZT09MjQwOSkgbmFtZTwtImVuZ2luZWVyaW5nIG1lY2hhbmljcyBwaHlzaWNzIGFuZCBzY2llbmNlIgogIGlmKGNvZGU9PTI0MTApIG5hbWU8LSJlbnZpcm9ubWVudGFsIGVuZ2luZWVyaW5nIgogIGlmKGNvZGU9PTI0MTEpIG5hbWU8LSJnZW9sb2dpY2FsIGFuZCBnZW9waHlzaWNhbCBlbmdpbmVlcmluZyIKICBpZihjb2RlPT0yNDEyKSBuYW1lPC0iaW5kdXN0cmlhbCBhbmQgbWFudWZhY3R1cmluZyBlbmdpbmVlcmluZyIKICBpZihjb2RlPT0yNDEzKSBuYW1lPC0ibWF0ZXJpYWxzIGVuZ25lZXJpbmcgYW5kIG1hdGVyaWFscyBzY2llbmNlIgogIGlmKGNvZGU9PTI0MTQpIG5hbWU8LSJtZWNoYW5pY2FsIGVuZ2luZWVyaW5nIgogIGlmKGNvZGU9PTI0MTUpIG5hbWU8LSJtZXRhbGx1cmdpY2FsIGVuZ2luZWVyaW5nIgogIGlmKGNvZGU9PTI0MTYpIG5hbWU8LSJtaW5pbmcgYW5kIG1pbmVyYWwgZW5naW5lZXJpbmciCiAgaWYoY29kZT09MjQxNykgbmFtZTwtIm5hdmFsIGFyY2hpdGVjdHVyZSBhbmQgbWFyaW5lIGVuZ2luZWVyaW5nIgogIGlmKGNvZGU9PTI0MTgpIG5hbWU8LSJudWNsZWFyIGVuZ2luZWVyaW5nIgogIGlmKGNvZGU9PTI0MTkpIG5hbWU8LSJwZXRyb2xldW0gZW5naW5lZXJpbmciCiAgaWYoY29kZT09MjQ5OSkgbmFtZTwtIm1pc2NlbGxhbmVvdXMgZW5naW5lZXJpbmciCiAgaWYoY29kZT09MjUwMCkgbmFtZTwtImVuZ2luZWVyaW5nIHRlY2hub2xvZ2llcyIKICBpZihjb2RlPT0yNTAxKSBuYW1lPC0iZW5naW5lZXJpbmcgYW5kIGluZHVzdHJpYWwgbWFuYWdlbWVudCIKICBpZihjb2RlPT0yNTAyKSBuYW1lPC0iZWxlY3RyaWNhbCBlbmdpbmVlcmluZyB0ZWNobm9sb2d5IgogIGlmKGNvZGU9PTI1MDMpIG5hbWU8LSJpbmR1c3RyaWFsIHByb2R1Y3Rpb24gdGVjaG5vbG9naWVzIgogIGlmKGNvZGU9PTI1MDQpIG5hbWU8LSJtZWNoYW5pY2FsIGVuZ2luZWVyaW5nIHJlbGF0ZWQgdGVjaG5vbG9naWVzIgogIGlmKGNvZGU9PTI1OTkpIG5hbWU8LSJtaXNjZWxsYW5lb3VzIGVuZ2luZWVyaW5nIHRlY2hub2xvZ2llcyIKICBpZihjb2RlPT0yNjAxKSBuYW1lPC0ibGluZ3Vpc3RpY3MgYW5kIGNvbXBhcmF0aXZlIGxhbmd1YWdlIGFuZCBsaXRlcmF0dXJlIgogIGlmKGNvZGU9PTI2MDIpIG5hbWU8LSJmcmVuY2ggZ2VybWFuIGxhdGluIGFuZCBvdGhlciBjb21tb24gZm9yZWlnbiBsYW5ndWFnZSBzdHVkaWVzIgogIGlmKGNvZGU9PTI2MDMpIG5hbWU8LSJvdGhlciBmb3JlaWduIGxhbmd1YWdlcyIKICBpZihjb2RlPT0yOTAxKSBuYW1lPC0iZmFtaWx5IGFuZCBjb25zdW1lciBzY2llbmNlcyIKICBpZihjb2RlPT0zMjAxKSBuYW1lPC0iY291cnQgcmVwb3J0aW5nIgogIGlmKGNvZGU9PTMyMDIpIG5hbWU8LSJwcmUtbGF3IGFuZCBsZWdhbCBzdHVkaWVzIgogIGlmKGNvZGU9PTMzMDEpIG5hbWU8LSJlbmdsaXNoIGxhbmd1YWdlIGFuZCBsaXRlcmF0dXJlIgogIGlmKGNvZGU9PTMzMDIpIG5hbWU8LSJjb21wb3NpdGlvbiBhbmQgcmhldG9yaWMiCiAgaWYoY29kZT09MzQwMSkgbmFtZTwtImxpYmVyYWwgYXJ0cyIKICBpZihjb2RlPT0zNDAyKSBuYW1lPC0iaHVtYW5pdGllcyIKICBpZihjb2RlPT0zNTAxKSBuYW1lPC0ibGlicmFyeSBzY2llbmNlIgogIGlmKGNvZGU9PTM2MDApIG5hbWU8LSJiaW9sb2d5IgogIGlmKGNvZGU9PTM2MDEpIG5hbWU8LSJiaW9jaGVtaWNhbCBzY2llbmNlcyIKICBpZihjb2RlPT0zNjAyKSBuYW1lPC0iYm90YW55IgogIGlmKGNvZGU9PTM2MDMpIG5hbWU8LSJtb2xlY3VsYXIgYmlvbG9neSIKICBpZihjb2RlPT0zNjA0KSBuYW1lPC0iZWNvbG9neSIKICBpZihjb2RlPT0zNjA1KSBuYW1lPC0iZ2VuZXRpY3MiCiAgaWYoY29kZT09MzYwNikgbmFtZTwtIm1pY3JvYmlvbG9neSIKICBpZihjb2RlPT0zNjA3KSBuYW1lPC0icGhhcm1hY29sb2d5IgogIGlmKGNvZGU9PTM2MDgpIG5hbWU8LSJwaHlzaW9sb2d5IgogIGlmKGNvZGU9PTM2MDkpIG5hbWU8LSJ6b29sb2d5IgogIGlmKGNvZGU9PTM2MTEpIG5hbWU8LSJuZXVyb3NjaWVuY2UiCiAgaWYoY29kZT09MzY5OSkgbmFtZTwtIm1pc2NlbGxhbmVvdXMgYmlvbG9neSIKICBpZihjb2RlPT0zNzAwKSBuYW1lPC0ibWF0aGVtYXRpY3MiCiAgaWYoY29kZT09MzcwMSkgbmFtZTwtImFwcGxpZWQgbWF0aGVtYXRpY3MiCiAgaWYoY29kZT09MzcwMikgbmFtZTwtInN0YXRpc3RpY3MgYW5kIGRlY2lzaW9uIHNjaWVuY2UiCiAgaWYoY29kZT09MzgwMSkgbmFtZTwtIm1pbGl0YXJ5IHRlY2hub2xvZ2llcyIKICBpZihjb2RlPT00MDAwKSBuYW1lPC0ibXVsdGkvaW50ZXJkaXNjaXBsaW5hcnkgc3R1ZGllcyIKICBpZihjb2RlPT00MDAxKSBuYW1lPC0iaW50ZXJjdWx0dXJhbCBhbmQgaW50ZXJuYXRpb25hbCBzdHVkaWVzIgogIGlmKGNvZGU9PTQwMDIpIG5hbWU8LSJudXRyaXRpb24gc2NpZW5jZXMiCiAgaWYoY29kZT09NDAwNSkgbmFtZTwtIm1hdGhlbWF0aWNzIGFuZCBjb21wdXRlciBzY2llbmNlIgogIGlmKGNvZGU9PTQwMDYpIG5hbWU8LSJjb2duaXRpdmUgc2NpZW5jZSBhbmQgYmlvcHN5Y2hvbG9neSIKICBpZihjb2RlPT00MDA3KSBuYW1lPC0iaW50ZXJkaXNjaXBsaW5hcnkgc29jaWFsIHNjaWVuY2VzIgogIGlmKGNvZGU9PTQxMDEpIG5hbWU8LSJwaHlzaWNhbCBmaXRuZXNzIHBhcmtzIHJlY3JlYXRpb24gYW5kIGxlaXN1cmUiCiAgaWYoY29kZT09NDgwMSkgbmFtZTwtInBoaWxvc29waHkgYW5kIHJlbGlnaW91cyBzdHVkaWVzIgogIGlmKGNvZGU9PTQ5MDEpIG5hbWU8LSJ0aGVvbG9neSBhbmQgcmVsaWdpb3VzIHZvY2F0aW9ucyIKICBpZihjb2RlPT01MDAwKSBuYW1lPC0icGh5c2ljYWwgc2NpZW5jZXMiCiAgaWYoY29kZT09NTAwMSkgbmFtZTwtImFzdHJvbm9teSBhbmQgYXN0cm9waHlzaWNzIgogIGlmKGNvZGU9PTUwMDIpIG5hbWU8LSJhdG1vc3BoZXJpYyBzY2llbmNlcyBhbmQgbWV0ZW9yb2xvZ3kiCiAgaWYoY29kZT09NTAwMykgbmFtZTwtImNoZW1pc3RyeSIKICBpZihjb2RlPT01MDA0KSBuYW1lPC0iZ2VvbG9neSBhbmQgZWFydGggc2NpZW5jZSIKICBpZihjb2RlPT01MDA1KSBuYW1lPC0iZ2Vvc2NpZW5jZXMiCiAgaWYoY29kZT09NTAwNikgbmFtZTwtIm9jZWFub2dyYXBoeSIKICBpZihjb2RlPT01MDA3KSBuYW1lPC0icGh5c2ljcyIKICBpZihjb2RlPT01MDA4KSBuYW1lPC0ibWF0ZXJpYWwgc2NpZW5jZSIKICBpZihjb2RlPT01MDk4KSBuYW1lPC0ibXVsdGktZGlzY2lwbGluYXJ5IG9yIGdlbmVyYWwgc2NpZW5jZSIKICBpZihjb2RlPT01MTAyKSBuYW1lPC0ibnVjbGVhciwgaW5kdXN0cmlhbCByYWRpb2xvZ3ksIGFuZCBiaW9sb2dpY2FsIHRlY2hub2xvZ2llcyIKICBpZihjb2RlPT01MjAwKSBuYW1lPC0icHN5Y2hvbG9neSIKICBpZihjb2RlPT01MjAxKSBuYW1lPC0iZWR1Y2F0aW9uYWwgcHN5Y2hvbG9neSIKICBpZihjb2RlPT01MjAyKSBuYW1lPC0iY2xpbmljYWwgcHN5Y2hvbG9neSIKICBpZihjb2RlPT01MjAzKSBuYW1lPC0iY291bnNlbGluZyBwc3ljaG9sb2d5IgogIGlmKGNvZGU9PTUyMDUpIG5hbWU8LSJpbmRzdXRyaWFsIGFuZCBvcmdhbml6YXRpb25hbCBwc3ljaG9sb2d5IgogIGlmKGNvZGU9PTUyMDYpIG5hbWU8LSJzb2NpYWwgcHN5Y2hvbG9neSIKICBpZihjb2RlPT01Mjk5KSBuYW1lPC0ibWlzY2VsbGFuZW91cyBwc3ljaG9sb2d5IgogIGlmKGNvZGU9PTUzMDEpIG5hbWU8LSJjcmltaW5hbCBqdXN0aWNlIGFuZCBmaXJlIHByb3RlY3Rpb24iCiAgaWYoY29kZT09NTQwMSkgbmFtZTwtInB1YmxpYyBhZG1pbmlzdHJhdGlvbiIKICBpZihjb2RlPT01NDAyKSBuYW1lPC0icHVibGljIHBvbGljeSIKICBpZihjb2RlPT01NDAzKSBuYW1lPC0iaHVtYW4gc2VydmljZXMgYW5kIGNvbW11bml0eSBvcmdhbml6YXRpb24iCiAgaWYoY29kZT09NTQwNCkgbmFtZTwtInNvY2lhbCB3b3JrIgogIGlmKGNvZGU9PTU1MDApIG5hbWU8LSJnZW5lcmFsIHNvY2lhbCBzY2llbmNlcyIKICBpZihjb2RlPT01NTAxKSBuYW1lPC0iZWNvbm9taWNzIgogIGlmKGNvZGU9PTU1MDIpIG5hbWU8LSJhbnRocm9wb2xvZ3kgYW5kIGFyY2hlb2xvZ3kiCiAgaWYoY29kZT09NTUwMykgbmFtZTwtImNyaW1pbm9sb2d5IgogIGlmKGNvZGU9PTU1MDQpIG5hbWU8LSJnZW9ncmFwaHkiCiAgaWYoY29kZT09NTUwNSkgbmFtZTwtImludGVybmF0aW5hbCByZWxhdGlvbnMiCiAgaWYoY29kZT09NTUwNikgbmFtZTwtInBvbGl0aWNhbCBzY2llbmNlIGFuZCBnb3Zlcm5tZW50IgogIGlmKGNvZGU9PTU1MDcpIG5hbWU8LSJzb2Npb2xvZ3kiCiAgaWYoY29kZT09NTU5OSkgbmFtZTwtIm1pc2NlbGxhbmVvdXMgc29jaWFsIHNjaWVuY2VzIgogIGlmKGNvZGU9PTU2MDEpIG5hbWU8LSJjb25zdHJ1Y3Rpb24gc2VydmljZXMiCiAgaWYoY29kZT09NTcwMSkgbmFtZTwtImVsZWN0cmljYWwsIG1lY2hhbmljYWwgYW5kIHByZWNpc2lvbiB0ZWNobm9sb2dpZXMgYW5kIHByb2R1Y3Rpb24iCiAgaWYoY29kZT09NTkwMSkgbmFtZTwtInRyYW5zcG9ydGF0aW9uIHNjaWVuY2VzIGFuZCB0ZWNobm9sb2dpZXMiCiAgaWYoY29kZT09NjAwMCkgbmFtZTwtImZpbmUgYXJ0cyIKICBpZihjb2RlPT02MDAxKSBuYW1lPC0iZHJhbWEgYW5kIHRoZWF0ZXIgYXJ0cyIKICBpZihjb2RlPT02MDAyKSBuYW1lPC0ibXVzaWMiCiAgaWYoY29kZT09NjAwMykgbmFtZTwtInZpc3VhbCBhbmQgcGVyZm9ybWluZyBhcnRzIgogIGlmKGNvZGU9PTYwMDQpIG5hbWU8LSJjb21tZXJjaWFsIGFydHMgYW5kIGdyYXBoaWMgZGVzaWduIgogIGlmKGNvZGU9PTYwMDUpIG5hbWU8LSJmaWxtIHZpZGVvIGFuZCBwaG90b2dyYXBoaWMgYXJ0cyIKICBpZihjb2RlPT02MDA2KSBuYW1lPC0iYXJ0IGhpc3RvcnkgYW5kIGNyaXRpY2lzbSIKICBpZihjb2RlPT02MDA3KSBuYW1lPC0ic3R1ZGlvIGFydHMiCiAgaWYoY29kZT09NjA5OSkgbmFtZTwtIm1pc2NlbGxhbmVvdXMgZmluZSBhcnRzIgogIGlmKGNvZGU9PTYxMDApIG5hbWU8LSJnZW5lcmFsIG1lZGljYWwgYW5kIGhlYWx0aCBzZXJ2aWNlcyIKICBpZihjb2RlPT02MTAyKSBuYW1lPC0iY29tbXVuaWNhdGlvbiBkaXNvcmRlcnMgc2NpZW5jZXMgYW5kIHNlcnZpY2VzIgogIGlmKGNvZGU9PTYxMDMpIG5hbWU8LSJoZWFsdGggYW5kIG1lZGljYWwgYWRtaW5pc3RyYXRpdmUgc2VydmljZXMiCiAgaWYoY29kZT09NjEwNCkgbmFtZTwtIm1lZGljYWwgYXNzaXN0aW5nIHNlcnZpY2VzIgogIGlmKGNvZGU9PTYxMDUpIG5hbWU8LSJtZWRpY2FsIHRlY2hub2xvZ2llcyB0ZWNobmljaWFucyIKICBpZihjb2RlPT02MTA2KSBuYW1lPC0iaGVhbHRoIGFuZCBtZWRpY2FsIHByZXBhcmF0b3J5IHByb2dyYW1zIgogIGlmKGNvZGU9PTYxMDcpIG5hbWU8LSJudXJzaW5nIgogIGlmKGNvZGU9PTYxMDgpIG5hbWU8LSJwaGFybWFjeSBwaGFybWFjZXV0aWNhbCBzY2llbmNlcyBhbmQgYWRtaW5pc3RyYXRpb24iCiAgaWYoY29kZT09NjEwOSkgbmFtZTwtInRyZWF0bWVudCB0aGVyYXB5IHByb2Zlc3Npb25zIgogIGlmKGNvZGU9PTYxMTApIG5hbWU8LSJjb21tdW5pdHkgYW5kIHB1YmxpYyBoZWFsdGgiCiAgaWYoY29kZT09NjE5OSkgbmFtZTwtIm1pc2NlbGxhbmVvdXMgaGVhbHRoIG1lZGljYWwgcHJvZmVzc2lvbnMiCiAgaWYoY29kZT09NjIwMCkgbmFtZTwtImdlbmVyYWwgYnVzaW5lc3MiCiAgaWYoY29kZT09NjIwMSkgbmFtZTwtImFjY291bnRpbmciCiAgaWYoY29kZT09NjIwMikgbmFtZTwtImFjdHVhcmlhbCBzY2llbmNlIgogIGlmKGNvZGU9PTYyMDMpIG5hbWU8LSJidXNpbmVzcyBtYW5hZ2VtZW50IGFuZCBhZG1pbmlzdHJhdGlvbiIKICBpZihjb2RlPT02MjA0KSBuYW1lPC0ib3BlcmF0aW9ucyBsb2dpc3RpY3MgYW5kIGUtY29tbWVyY2UiCiAgaWYoY29kZT09NjIwNSkgbmFtZTwtImJ1c2luZXNzIGVjb25vbWljcyIKICBpZihjb2RlPT02MjA2KSBuYW1lPC0ibWFya2V0aW5nIGFuZCBtYXJrZXRpbmcgcmVzZWFyY2giCiAgaWYoY29kZT09NjIwNykgbmFtZTwtImZpbmFuY2UiCiAgaWYoY29kZT09NjIwOSkgbmFtZTwtImh1bWFuIHJlc291cmNlcyBhbmQgcGVyc29ubmVsIG1hbmFnZW1lbnQiCiAgaWYoY29kZT09NjIxMCkgbmFtZTwtImludGVybmF0aW9uYWwgYnVzaW5lc3MiCiAgaWYoY29kZT09NjIxMSkgbmFtZTwtImhvc3BpdGFsaXR5IG1hbmFnZW1lbnQiCiAgaWYoY29kZT09NjIxMikgbmFtZTwtIm1hbmFnZW1lbnQgaW5mb3JtYXRpb24gc3lzdGVtcyBhbmQgc3RhdGlzdGljcyIKICBpZihjb2RlPT02Mjk5KSBuYW1lPC0ibWlzY2VsbGFuZW91cyBidXNpbmVzcyBhbmQgbWVkaWNhbCBhZG1pbmlzdHJhdGlvbiIKICBpZihjb2RlPT02NDAyKSBuYW1lPC0iaGlzdG9yeSIKICBpZihjb2RlPT02NDAzKSBuYW1lPC0idW5pdGVkIHN0YXRlcyBoaXN0b3J5IgogIHJldHVybihuYW1lKQp9CgojIFRoZW4gSSB3aWxsIHRyYW5zZmVyIG1ham9yIGNvZGVzIHRvIG1ham9yIG5hbWVzIGFuZCBzdGVtIGNvZGUgdG8gc3RlbS9ub24tc3RlbS4KZm9yKGkgaW4gMTpucm93KG1zMTRjaXR0b3ApKXsKICBtczE0Y2l0dG9wW2ksd2hpY2goY29sbmFtZXMobXMxNGNpdHRvcCk9PSJtYWpvciIpXTwtY29kZW5hbWUobXMxNGNpdHRvcCRtYWpvcltpXSkKfQpmb3IoaSBpbiAxOm5yb3cobXMxNG5jaXR0b3ApKXsKICBtczE0bmNpdHRvcFtpLHdoaWNoKGNvbG5hbWVzKG1zMTRuY2l0dG9wKT09Im1ham9yIildPC1jb2RlbmFtZShtczE0bmNpdHRvcCRtYWpvcltpXSkKfQptczE0Y2l0dG9wW21zMTRjaXR0b3Akc3RlbT09MSx3aGljaChjb2xuYW1lcyhtczE0Y2l0dG9wKT09InN0ZW0iKV08LSJzdGVtIgptczE0Y2l0dG9wW21zMTRjaXR0b3Akc3RlbT09MCx3aGljaChjb2xuYW1lcyhtczE0Y2l0dG9wKT09InN0ZW0iKV08LSJub24tc3RlbSIKbXMxNG5jaXR0b3BbbXMxNG5jaXR0b3Akc3RlbT09MSx3aGljaChjb2xuYW1lcyhtczE0bmNpdHRvcCk9PSJzdGVtIildPC0ic3RlbSIKbXMxNG5jaXR0b3BbbXMxNG5jaXR0b3Akc3RlbT09MCx3aGljaChjb2xuYW1lcyhtczE0bmNpdHRvcCk9PSJzdGVtIildPC0ibm9uLXN0ZW0iCiMgbXMxNGNpdHRvcCwgbXMxNG5jaXR0b3Agd2lsbCBiZSB1c2VkIGxhdGVyLgoKIyBOb3csIEkgbmVlZCB0byBkbyBzdGVtIHZzIG9jY3VwYXRpb24gdHlwZS4Kc3RlbXdvcmsxNGNpdDwtcHVzMTRjaXQlPiVmaWx0ZXIoU1RFTT09MSkKc3RlbXdvcmsxNG5jaXQ8LXB1czE0bmNpdCU+JWZpbHRlcihTVEVNPT0xKQpuc3RlbXdvcmsxNGNpdDwtcHVzMTRjaXQlPiVmaWx0ZXIoU1RFTT09MCkKbnN0ZW13b3JrMTRuY2l0PC1wdXMxNG5jaXQlPiVmaWx0ZXIoU1RFTT09MCkKdG9wc3RlbXdvcmsxNGNpdDwtYXMuZGF0YS5mcmFtZShzb3J0KHRhYmxlKHN0ZW13b3JrMTRjaXQkT0NDUC5UWVBFKSxkZWNyZWFzaW5nPVQpKQp0b3BzdGVtd29yazE0bmNpdDwtYXMuZGF0YS5mcmFtZShzb3J0KHRhYmxlKHN0ZW13b3JrMTRuY2l0JE9DQ1AuVFlQRSksZGVjcmVhc2luZz1UKSkKdG9wbnN0ZW13b3JrMTRjaXQ8LWFzLmRhdGEuZnJhbWUoc29ydCh0YWJsZShuc3RlbXdvcmsxNGNpdCRPQ0NQLlRZUEUpLGRlY3JlYXNpbmc9VCkpCnRvcG5zdGVtd29yazE0bmNpdDwtYXMuZGF0YS5mcmFtZShzb3J0KHRhYmxlKG5zdGVtd29yazE0bmNpdCRPQ0NQLlRZUEUpLGRlY3JlYXNpbmc9VCkpCnRvcHN0ZW13b3JrMTRjaXQ8LWNiaW5kKHRvcHN0ZW13b3JrMTRjaXQsYygic3RlbSIpKQp0b3BzdGVtd29yazE0bmNpdDwtY2JpbmQodG9wc3RlbXdvcmsxNG5jaXQsYygic3RlbSIpKQp0b3Buc3RlbXdvcmsxNGNpdDwtY2JpbmQodG9wbnN0ZW13b3JrMTRjaXQsYygibm9uLXN0ZW0iKSkKdG9wbnN0ZW13b3JrMTRuY2l0PC1jYmluZCh0b3Buc3RlbXdvcmsxNG5jaXQsYygibm9uLXN0ZW0iKSkKY29sbmFtZXModG9wc3RlbXdvcmsxNGNpdCk8LWMoImZyZXF1ZW5jeSIsInN0ZW0iKQpjb2xuYW1lcyh0b3BzdGVtd29yazE0bmNpdCk8LWMoImZyZXF1ZW5jeSIsInN0ZW0iKQpjb2xuYW1lcyh0b3Buc3RlbXdvcmsxNGNpdCk8LWMoImZyZXF1ZW5jeSIsInN0ZW0iKQpjb2xuYW1lcyh0b3Buc3RlbXdvcmsxNG5jaXQpPC1jKCJmcmVxdWVuY3kiLCJzdGVtIikKdG9wc3RlbXdvcmsxNGNpdDwtdG9wc3RlbXdvcmsxNGNpdCU+JW11dGF0ZSh3b3JrPXJvd25hbWVzKHRvcHN0ZW13b3JrMTRjaXQpKQp0b3BzdGVtd29yazE0bmNpdDwtdG9wc3RlbXdvcmsxNG5jaXQlPiVtdXRhdGUod29yaz1yb3duYW1lcyh0b3BzdGVtd29yazE0bmNpdCkpCnRvcG5zdGVtd29yazE0Y2l0PC10b3Buc3RlbXdvcmsxNGNpdCU+JW11dGF0ZSh3b3JrPXJvd25hbWVzKHRvcG5zdGVtd29yazE0Y2l0KSkKdG9wbnN0ZW13b3JrMTRuY2l0PC10b3Buc3RlbXdvcmsxNG5jaXQlPiVtdXRhdGUod29yaz1yb3duYW1lcyh0b3Buc3RlbXdvcmsxNG5jaXQpKQp0b3B3b3JrMTRjaXQ8LXJiaW5kKHRvcHN0ZW13b3JrMTRjaXQsdG9wbnN0ZW13b3JrMTRjaXQpCnRvcHdvcmsxNG5jaXQ8LXJiaW5kKHRvcHN0ZW13b3JrMTRuY2l0LHRvcG5zdGVtd29yazE0bmNpdCkKdG9wd29yazE0Y2l0W3RvcHdvcmsxNGNpdCR3b3JrPT0iMCIsd2hpY2goY29sbmFtZXModG9wd29yazE0Y2l0KT09IndvcmsiKV08LSJOT05FIgp0b3B3b3JrMTRuY2l0W3RvcHdvcmsxNG5jaXQkd29yaz09IjAiLHdoaWNoKGNvbG5hbWVzKHRvcHdvcmsxNG5jaXQpPT0id29yayIpXTwtIk5PTkUiCnRvcHdvcmsxNGNpdDwtdG9wd29yazE0Y2l0JT4lbXV0YXRlKHByb3BvcnRpb249ZnJlcXVlbmN5L3N1bShmcmVxdWVuY3kpKQp0b3B3b3JrMTRuY2l0PC10b3B3b3JrMTRuY2l0JT4lbXV0YXRlKHByb3BvcnRpb249ZnJlcXVlbmN5L3N1bShmcmVxdWVuY3kpKQojIHRvcHdvcmsxNGNpdCx0b3B3b3JrMTRuY2l0IHdpbGwgYmUgdXNlZC4KCiMgTm93LCBJIGFtIHJlYWR5IGZvciBTYW5rZXkgcGxvdC4KbXN3MTRjaXQxPC1tczE0Y2l0dG9wWywyOjRdCmNvbG5hbWVzKG1zdzE0Y2l0MSk8LWMoIm9yaWdpbiIsInZpc2l0Iiwid2VpZ2h0IikKbXN3MTRjaXQyPC10b3B3b3JrMTRjaXRbLDI6NF0KY29sbmFtZXMobXN3MTRjaXQyKTwtYygib3JpZ2luIiwidmlzaXQiLCJ3ZWlnaHQiKQptc3cxNGNpdDwtcmJpbmQobXN3MTRjaXQxLG1zdzE0Y2l0MikKbXN3MTRjaXRbLDFdPC1hcy5mYWN0b3IobXN3MTRjaXRbLDFdKQptc3cxNGNpdFssMl08LWFzLmZhY3Rvcihtc3cxNGNpdFssMl0pCm1zdzE0Y2l0WywzXTwtYXMubnVtZXJpYyhtc3cxNGNpdFssM10pCgptc3cxNG5jaXQxPC1tczE0bmNpdHRvcFssMjo0XQpjb2xuYW1lcyhtc3cxNG5jaXQxKTwtYygib3JpZ2luIiwidmlzaXQiLCJ3ZWlnaHQiKQptc3cxNG5jaXQyPC10b3B3b3JrMTRuY2l0WywyOjRdCmNvbG5hbWVzKG1zdzE0bmNpdDIpPC1jKCJvcmlnaW4iLCJ2aXNpdCIsIndlaWdodCIpCm1zdzE0bmNpdDwtcmJpbmQobXN3MTRuY2l0MSxtc3cxNG5jaXQyKQptc3cxNG5jaXRbLDFdPC1hcy5mYWN0b3IobXN3MTRuY2l0WywxXSkKbXN3MTRuY2l0WywyXTwtYXMuZmFjdG9yKG1zdzE0bmNpdFssMl0pCm1zdzE0bmNpdFssM108LWFzLm51bWVyaWMobXN3MTRuY2l0WywzXSkKYGBgCgojIyMjIyBGb3IgY2l0aXplbnM6CmBgYHtyLCByZXN1bHRzPSdhc2lzJywgdGlkeT1UUlVFLCBtZXNzYWdlPUZBTFNFLCBmaWcud2lkdGg9N30KbGlicmFyeShnb29nbGVWaXMpCm9wPC1vcHRpb25zKGd2aXMucGxvdC50YWc9J2NoYXJ0JykKc2Fua2V5Y2l0PC1ndmlzU2Fua2V5KG1zdzE0Y2l0LGZyb209Im9yaWdpbiIsdG89InZpc2l0Iix3ZWlnaHQ9IndlaWdodCIsb3B0aW9ucz1saXN0KGhlaWdodD03MDAsd2lkdGg9OTAwLHNhbmtleT0ie2xpbms6e2NvbG9yOntmaWxsOidkZWVwc2t5Ymx1ZSd9fSxub2RlOnt3aWR0aDoyMCxsYWJlbDp7Zm9udFNpemU6MTIsYm9sZDp0cnVlfX19IikpCnBsb3Qoc2Fua2V5Y2l0KQpgYGAKCgoKIyMjIyMgRm9yIG5vbi1jaXRpemVuczoKYGBge3IsIHJlc3VsdHM9J2FzaXMnLCB0aWR5PVRSVUUsIG1lc3NhZ2U9RkFMU0UsIGZpZy53aWR0aD03fQpzYW5rZXlub25jaXQ8LWd2aXNTYW5rZXkobXN3MTRuY2l0LGZyb209Im9yaWdpbiIsdG89InZpc2l0Iix3ZWlnaHQ9IndlaWdodCIsb3B0aW9ucz1saXN0KGhlaWdodD03MDAsd2lkdGg9OTAwLHNhbmtleT0ie2xpbms6e2NvbG9yOntmaWxsOidtZWRpdW1zcHJpbmdncmVlbid9fSxub2RlOnt3aWR0aDoyMCxsYWJlbDp7Zm9udFNpemU6MTIsYm9sZDp0cnVlfX19IikpCnByaW50KHNhbmtleW5vbmNpdCwnY2hhcnQnKQpvcHRpb25zKG9wKQpgYGAKCiMjIyMgKDMpIEluZHVzdHJ5IENob2ljZSBBZnRlciBHcmFkdWF0aW9uCgpUbyBmdXJ0aGVyIHN0dWR5IGhvdyBwZW9wbGUgb2Ygc3BlY2lmaWMgU1RFTSBkZWdyZWUgZ28gaW50byBkaWZmZXJlbnQgaW5kdXN0cmllcywgd2UgZHJhdyB0aGUgZm9sbG93aW5nIGNpcmN1bGFyIHBsb3RzLiBFYWNoIHBsb3QgY29ycmVzcG9uc2VzIHRvIGVpdGhlciBjaXRpemVuIG9yIG5vbi1jaXRpemVuIGFuZCBlaXRoZXIgU1RFTSBkZWdyZWUgb3Igbm9uLVNURU0gZGVncmVlLgpUaGVzZSBmaWd1cmVzIHN1Z2dlc3QgYSBsb3Qgb2YgaW5mb3JtYXRpb24gYnV0IGR1ZSB0byB0aGUgdGltZSBjb25zdHJhaW50cywgd2Ugd2lsbCBub3QgdGFsayBhYm91dCB0aGVtIGR1cmluZyB0aGlzIHByZXNlbnRhdGlvbi4KYGBge3J9CiMgTm93LCBJIHdpbGwgZG8gY2lyY3VsYXIgcGxvdHMgZm9yIG1ham9ycyBpbiBzdGVtIHZzIG9jY3VwYXRpb24gYW5kIG1ham9ycyBpbiBub24tc3RlbSB2cyBvY2N1cGF0aW9uIGZvciBjaXRpemVucyBhbmQgbm9uLWNpdGl6ZW5zLgpwdXMxNGNpdHN0ZW08LXB1czE0Y2l0W3B1czE0Y2l0JFNURU09PTEsXQpwdXMxNGNpdG5zdGVtPC1wdXMxNGNpdFtwdXMxNGNpdCRTVEVNPT0wLF0KcHVzMTRuY2l0c3RlbTwtcHVzMTRuY2l0W3B1czE0bmNpdCRTVEVNPT0xLF0KcHVzMTRuY2l0bnN0ZW08LXB1czE0bmNpdFtwdXMxNG5jaXQkU1RFTT09MCxdCgojIGVhY2ggdG9wIG1ham9yCnB1czE0Y2l0c3RlbXRvcDwtbGlzdCgpCmZvcihpIGluIDE6MTApewogIHB1czE0Y2l0c3RlbXRvcFtbaV1dPC1wdXMxNGNpdHN0ZW0lPiVmaWx0ZXIoRk9EMVA9PWFzLm51bWVyaWMobXMxNGNpdHRvcHMkbWFqb3JbaV0pKQp9CnB1czE0Y2l0bnN0ZW10b3A8LWxpc3QoKQpmb3IoaSBpbiAxOjEwKXsKICBwdXMxNGNpdG5zdGVtdG9wW1tpXV08LXB1czE0Y2l0bnN0ZW0lPiVmaWx0ZXIoRk9EMVA9PWFzLm51bWVyaWMobXMxNGNpdHRvcG5zJG1ham9yW2ldKSkKfQpwdXMxNG5jaXRzdGVtdG9wPC1saXN0KCkKZm9yKGkgaW4gMToxMCl7CiAgcHVzMTRuY2l0c3RlbXRvcFtbaV1dPC1wdXMxNG5jaXRzdGVtJT4lZmlsdGVyKEZPRDFQPT1hcy5udW1lcmljKG1zMTRuY2l0dG9wcyRtYWpvcltpXSkpCn0KcHVzMTRuY2l0bnN0ZW10b3A8LWxpc3QoKQpmb3IoaSBpbiAxOjEwKXsKICBwdXMxNG5jaXRuc3RlbXRvcFtbaV1dPC1wdXMxNG5jaXRuc3RlbSU+JWZpbHRlcihGT0QxUD09YXMubnVtZXJpYyhtczE0bmNpdHRvcG5zJG1ham9yW2ldKSkKfQoKIyBhbW91bnQgb2Ygam9icyBpbiBlYWNoIGZpZWxkIGZvciBlYWNoIHRvcCBtYWpvcgpjaXRzdGVtZjE0PC1saXN0KCkKZm9yKGkgaW4gMToxMCl7CiAgY2l0c3RlbWYxNFtbaV1dPC1hcy5kYXRhLmZyYW1lKHNvcnQodGFibGUocHVzMTRjaXRzdGVtdG9wW1tpXV0kT0NDUC5UWVBFKSxkZWNyZWFzaW5nPVQpKQp9CmNpdG5zdGVtZjE0PC1saXN0KCkKZm9yKGkgaW4gMToxMCl7CiAgY2l0bnN0ZW1mMTRbW2ldXTwtYXMuZGF0YS5mcmFtZShzb3J0KHRhYmxlKHB1czE0Y2l0bnN0ZW10b3BbW2ldXSRPQ0NQLlRZUEUpLGRlY3JlYXNpbmc9VCkpCn0KbmNpdHN0ZW1mMTQ8LWxpc3QoKQpmb3IoaSBpbiAxOjEwKXsKICBuY2l0c3RlbWYxNFtbaV1dPC1hcy5kYXRhLmZyYW1lKHNvcnQodGFibGUocHVzMTRuY2l0c3RlbXRvcFtbaV1dJE9DQ1AuVFlQRSksZGVjcmVhc2luZz1UKSkKfQpuY2l0bnN0ZW1mMTQ8LWxpc3QoKQpmb3IoaSBpbiAxOjEwKXsKICBuY2l0bnN0ZW1mMTRbW2ldXTwtYXMuZGF0YS5mcmFtZShzb3J0KHRhYmxlKHB1czE0bmNpdG5zdGVtdG9wW1tpXV0kT0NDUC5UWVBFKSxkZWNyZWFzaW5nPVQpKQp9Cgpmb3IoaSBpbiAxOjEwKXsKICBjaXRzdGVtZjE0W1tpXV08LWNpdHN0ZW1mMTRbW2ldXSU+JW11dGF0ZSh0eXBlPXJvd25hbWVzKGNpdHN0ZW1mMTRbW2ldXSkpCiAgY2l0bnN0ZW1mMTRbW2ldXTwtY2l0bnN0ZW1mMTRbW2ldXSU+JW11dGF0ZSh0eXBlPXJvd25hbWVzKGNpdG5zdGVtZjE0W1tpXV0pKQogIG5jaXRzdGVtZjE0W1tpXV08LW5jaXRzdGVtZjE0W1tpXV0lPiVtdXRhdGUodHlwZT1yb3duYW1lcyhuY2l0c3RlbWYxNFtbaV1dKSkKICBuY2l0bnN0ZW1mMTRbW2ldXTwtbmNpdG5zdGVtZjE0W1tpXV0lPiVtdXRhdGUodHlwZT1yb3duYW1lcyhuY2l0bnN0ZW1mMTRbW2ldXSkpCiAgY29sbmFtZXMoY2l0c3RlbWYxNFtbaV1dKVsxXTwtImZyZXF1ZW5jeSIKICBjb2xuYW1lcyhjaXRuc3RlbWYxNFtbaV1dKVsxXTwtImZyZXF1ZW5jeSIKICBjb2xuYW1lcyhuY2l0c3RlbWYxNFtbaV1dKVsxXTwtImZyZXF1ZW5jeSIKICBjb2xuYW1lcyhuY2l0bnN0ZW1mMTRbW2ldXSlbMV08LSJmcmVxdWVuY3kiCn0KZm9yKGkgaW4gMToxMCl7CiAgY2l0c3RlbWYxNFtbaV1dPC1jaXRzdGVtZjE0W1tpXV1bb3JkZXIoY2l0c3RlbWYxNFtbaV1dJHR5cGUpLF0KICBjaXRuc3RlbWYxNFtbaV1dPC1jaXRuc3RlbWYxNFtbaV1dW29yZGVyKGNpdG5zdGVtZjE0W1tpXV0kdHlwZSksXQogIG5jaXRzdGVtZjE0W1tpXV08LW5jaXRzdGVtZjE0W1tpXV1bb3JkZXIobmNpdHN0ZW1mMTRbW2ldXSR0eXBlKSxdCiAgbmNpdG5zdGVtZjE0W1tpXV08LW5jaXRuc3RlbWYxNFtbaV1dW29yZGVyKG5jaXRuc3RlbWYxNFtbaV1dJHR5cGUpLF0KfQoKY2l0c3RlbW0xNDwtbWF0cml4KDAsbnJvdz0xMCxuY29sPTI1KQpjaXRuc3RlbW0xNDwtbWF0cml4KDAsbnJvdz0xMCxuY29sPTI1KQpuY2l0c3RlbW0xNDwtbWF0cml4KDAsbnJvdz0xMCxuY29sPTI1KQpuY2l0bnN0ZW1tMTQ8LW1hdHJpeCgwLG5yb3c9MTAsbmNvbD0yNSkKZm9yKGkgaW4gMToxMCl7CiAgY2l0c3RlbW0xNFtpLF08LWNpdHN0ZW1mMTRbW2ldXSRmcmVxdWVuY3lbMjoyNl0KICBjaXRuc3RlbW0xNFtpLF08LWNpdG5zdGVtZjE0W1tpXV0kZnJlcXVlbmN5WzI6MjZdCiAgbmNpdHN0ZW1tMTRbaSxdPC1uY2l0c3RlbWYxNFtbaV1dJGZyZXF1ZW5jeVsyOjI2XQogIG5jaXRuc3RlbW0xNFtpLF08LW5jaXRuc3RlbWYxNFtbaV1dJGZyZXF1ZW5jeVsyOjI2XQp9CmNvbG5hbWVzKGNpdHN0ZW1tMTQpPC1jaXRzdGVtZjE0W1sxXV0kdHlwZVsyOjI2XQpjb2xuYW1lcyhjaXRuc3RlbW0xNCk8LWNpdG5zdGVtZjE0W1sxXV0kdHlwZVsyOjI2XQpjb2xuYW1lcyhuY2l0c3RlbW0xNCk8LW5jaXRzdGVtZjE0W1sxXV0kdHlwZVsyOjI2XQpjb2xuYW1lcyhuY2l0bnN0ZW1tMTQpPC1uY2l0bnN0ZW1mMTRbWzFdXSR0eXBlWzI6MjZdCnJvd25hbWVzKGNpdHN0ZW1tMTQpPC1jKDEsMiwzLDQsNSw2LDcsOCw5LDEwKQpyb3duYW1lcyhjaXRuc3RlbW0xNCk8LWMoMSwyLDMsNCw1LDYsNyw4LDksMTApCnJvd25hbWVzKG5jaXRzdGVtbTE0KTwtYygxLDIsMyw0LDUsNiw3LDgsOSwxMCkKcm93bmFtZXMobmNpdG5zdGVtbTE0KTwtYygxLDIsMyw0LDUsNiw3LDgsOSwxMCkKZm9yKGkgaW4gMToxMCl7CiAgcm93bmFtZXMoY2l0c3RlbW0xNClbaV08LWNvZGVuYW1lKG1zMTRjaXR0b3BzJG1ham9yW2ldKQogIHJvd25hbWVzKGNpdG5zdGVtbTE0KVtpXTwtY29kZW5hbWUobXMxNGNpdHRvcG5zJG1ham9yW2ldKQogIHJvd25hbWVzKG5jaXRzdGVtbTE0KVtpXTwtY29kZW5hbWUobXMxNG5jaXR0b3BzJG1ham9yW2ldKQogIHJvd25hbWVzKG5jaXRuc3RlbW0xNClbaV08LWNvZGVuYW1lKG1zMTRuY2l0dG9wbnMkbWFqb3JbaV0pCn0KYGBgCiMjIyMjIHZpc3VhbGl6YXRpb24gIzEgQ2l0aXplbiBTVEVNCmBgYHtyfQpsaWJyYXJ5KHJlY2hhcnRzKQp6ZXJvMTAxMDwtbWF0cml4KDAsMTAsMTApCnplcm8yNTI1PC1tYXRyaXgoMCwyNSwyNSkKY2l0c3RlbW0xNGMxPC1jYmluZCh6ZXJvMTAxMCxjaXRzdGVtbTE0KQpjaXRzdGVtbTE0YzI8LWNiaW5kKHQoY2l0c3RlbW0xNCksemVybzI1MjUpCmNpdHN0ZW1tMTRjPC1yYmluZChjaXRzdGVtbTE0YzEsY2l0c3RlbW0xNGMyKQpjaG9yZGNpdHN0ZW09bGlzdCh0aXRsZT1saXN0KHRleHQ9J0NpdGl6ZW4gU1RFTScsc3VidGV4dD0nRnJvbSBKYXZhU2NyaXB0Jyx4PSdyaWdodCcseT0nYm90dG9tJyksCnRvb2x0aXA9bGlzdCh0cmlnZ2VyPSdpdGVtJyxmb3JtYXR0ZXI9SlMoJ2Z1bmN0aW9uKHBhcmFtcyl7CiAgICAgICAgICAgICAgICAgICAgICBpZiAocGFyYW1zLmluZGljYXRvcjIpIHsgLy8gaXMgZWRnZQogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcGFyYW1zLnZhbHVlLndlaWdodDsKICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7Ly8gaXMgbm9kZQogICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcGFyYW1zLm5hbWUKICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9JykpLAp0b29sYm94PWxpc3Qoc2hvdz1UUlVFLGZlYXR1cmU9bGlzdChyZXN0b3JlPWxpc3Qoc2hvdz1UUlVFKSxtYWdpY1R5cGU9bGlzdChzaG93PVRSVUUsdHlwZT1jKCdmb3JjZScsJ2Nob3JkJykpLApzYXZlQXNJbWFnZT1saXN0KHNob3c9VFJVRSkpKSwKbGVnZW5kPWxpc3QoeD0nbGVmdCcsZGF0YT1jKHJvd25hbWVzKGNpdHN0ZW1tMTQpLGNvbG5hbWVzKGNpdHN0ZW1tMTQpKSksCnNlcmllcz1saXN0KGxpc3QodHlwZT0nY2hvcmQnLHNob3dTY2FsZT1GQUxTRSxzaG93U2NhbGVUZXh0PUZBTFNFLApkYXRhPWxpc3QobGlzdChuYW1lPXJvd25hbWVzKGNpdHN0ZW1tMTQpWzFdKSxsaXN0KG5hbWU9cm93bmFtZXMoY2l0c3RlbW0xNClbMl0pLGxpc3QobmFtZT1yb3duYW1lcyhjaXRzdGVtbTE0KVszXSksbGlzdChuYW1lPXJvd25hbWVzKGNpdHN0ZW1tMTQpWzRdKSxsaXN0KG5hbWU9cm93bmFtZXMoY2l0c3RlbW0xNClbNV0pLGxpc3QobmFtZT1yb3duYW1lcyhjaXRzdGVtbTE0KVs2XSksbGlzdChuYW1lPXJvd25hbWVzKGNpdHN0ZW1tMTQpWzddKSxsaXN0KG5hbWU9cm93bmFtZXMoY2l0c3RlbW0xNClbOF0pLGxpc3QobmFtZT1yb3duYW1lcyhjaXRzdGVtbTE0KVs5XSksbGlzdChuYW1lPXJvd25hbWVzKGNpdHN0ZW1tMTQpWzEwXSksbGlzdChuYW1lPWNvbG5hbWVzKGNpdHN0ZW1tMTQpWzFdKSxsaXN0KG5hbWU9Y29sbmFtZXMoY2l0c3RlbW0xNClbMl0pLGxpc3QobmFtZT1jb2xuYW1lcyhjaXRzdGVtbTE0KVszXSksbGlzdChuYW1lPWNvbG5hbWVzKGNpdHN0ZW1tMTQpWzRdKSxsaXN0KG5hbWU9Y29sbmFtZXMoY2l0c3RlbW0xNClbNV0pLGxpc3QobmFtZT1jb2xuYW1lcyhjaXRzdGVtbTE0KVs2XSksbGlzdChuYW1lPWNvbG5hbWVzKGNpdHN0ZW1tMTQpWzddKSxsaXN0KG5hbWU9Y29sbmFtZXMoY2l0c3RlbW0xNClbOF0pLGxpc3QobmFtZT1jb2xuYW1lcyhjaXRzdGVtbTE0KVs5XSksbGlzdChuYW1lPWNvbG5hbWVzKGNpdHN0ZW1tMTQpWzEwXSksbGlzdChuYW1lPWNvbG5hbWVzKGNpdHN0ZW1tMTQpWzExXSksbGlzdChuYW1lPWNvbG5hbWVzKGNpdHN0ZW1tMTQpWzEyXSksbGlzdChuYW1lPWNvbG5hbWVzKGNpdHN0ZW1tMTQpWzEzXSksbGlzdChuYW1lPWNvbG5hbWVzKGNpdHN0ZW1tMTQpWzE0XSksbGlzdChuYW1lPWNvbG5hbWVzKGNpdHN0ZW1tMTQpWzE1XSksbGlzdChuYW1lPWNvbG5hbWVzKGNpdHN0ZW1tMTQpWzE2XSksbGlzdChuYW1lPWNvbG5hbWVzKGNpdHN0ZW1tMTQpWzE3XSksbGlzdChuYW1lPWNvbG5hbWVzKGNpdHN0ZW1tMTQpWzE4XSksbGlzdChuYW1lPWNvbG5hbWVzKGNpdHN0ZW1tMTQpWzE5XSksbGlzdChuYW1lPWNvbG5hbWVzKGNpdHN0ZW1tMTQpWzIwXSksbGlzdChuYW1lPWNvbG5hbWVzKGNpdHN0ZW1tMTQpWzIxXSksbGlzdChuYW1lPWNvbG5hbWVzKGNpdHN0ZW1tMTQpWzIyXSksbGlzdChuYW1lPWNvbG5hbWVzKGNpdHN0ZW1tMTQpWzIzXSksbGlzdChuYW1lPWNvbG5hbWVzKGNpdHN0ZW1tMTQpWzI0XSksbGlzdChuYW1lPWNvbG5hbWVzKGNpdHN0ZW1tMTQpWzI1XSkpLAppdGVtU3R5bGU9bGlzdChub3JtYWw9bGlzdChsYWJlbD1saXN0KHNob3c9VFJVRSkpKSwKbWF0cml4PWNpdHN0ZW1tMTRjKSkpCmVjaGFydChjaG9yZGNpdHN0ZW0pCmBgYAojIyMjIyB2aXN1YWxpemF0aW9uICMyIENpdGl6ZW4gTm9uLVNURU0KYGBge3J9Cnplcm8xMDEwPC1tYXRyaXgoMCwxMCwxMCkKemVybzI1MjU8LW1hdHJpeCgwLDI1LDI1KQpjaXRuc3RlbW0xNGMxPC1jYmluZCh6ZXJvMTAxMCxjaXRuc3RlbW0xNCkKY2l0bnN0ZW1tMTRjMjwtY2JpbmQodChjaXRuc3RlbW0xNCksemVybzI1MjUpCmNpdG5zdGVtbTE0YzwtcmJpbmQoY2l0bnN0ZW1tMTRjMSxjaXRuc3RlbW0xNGMyKQpjaG9yZGNpdG5zdGVtPWxpc3QodGl0bGU9bGlzdCh0ZXh0PSdDaXRpemVuIG5vbi1TVEVNJyxzdWJ0ZXh0PSdGcm9tIEphdmFTY3JpcHQnLHg9J3JpZ2h0Jyx5PSdib3R0b20nKSwKdG9vbHRpcD1saXN0KHRyaWdnZXI9J2l0ZW0nLGZvcm1hdHRlcj1KUygnZnVuY3Rpb24ocGFyYW1zKXsKICAgICAgICAgICAgICAgICAgICAgIGlmIChwYXJhbXMuaW5kaWNhdG9yMikgeyAvLyBpcyBlZGdlCiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBwYXJhbXMudmFsdWUud2VpZ2h0OwogICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsvLyBpcyBub2RlCiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBwYXJhbXMubmFtZQogICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0nKSksCnRvb2xib3g9bGlzdChzaG93PVRSVUUsZmVhdHVyZT1saXN0KHJlc3RvcmU9bGlzdChzaG93PVRSVUUpLG1hZ2ljVHlwZT1saXN0KHNob3c9VFJVRSx0eXBlPWMoJ2ZvcmNlJywnY2hvcmQnKSksCnNhdmVBc0ltYWdlPWxpc3Qoc2hvdz1UUlVFKSkpLApsZWdlbmQ9bGlzdCh4PSdsZWZ0JyxkYXRhPWMocm93bmFtZXMoY2l0bnN0ZW1tMTQpLGNvbG5hbWVzKGNpdG5zdGVtbTE0KSkpLApzZXJpZXM9bGlzdChsaXN0KHR5cGU9J2Nob3JkJyxzaG93U2NhbGU9RkFMU0Usc2hvd1NjYWxlVGV4dD1GQUxTRSwKZGF0YT1saXN0KGxpc3QobmFtZT1yb3duYW1lcyhjaXRuc3RlbW0xNClbMV0pLGxpc3QobmFtZT1yb3duYW1lcyhjaXRuc3RlbW0xNClbMl0pLGxpc3QobmFtZT1yb3duYW1lcyhjaXRuc3RlbW0xNClbM10pLGxpc3QobmFtZT1yb3duYW1lcyhjaXRuc3RlbW0xNClbNF0pLGxpc3QobmFtZT1yb3duYW1lcyhjaXRuc3RlbW0xNClbNV0pLGxpc3QobmFtZT1yb3duYW1lcyhjaXRuc3RlbW0xNClbNl0pLGxpc3QobmFtZT1yb3duYW1lcyhjaXRuc3RlbW0xNClbN10pLGxpc3QobmFtZT1yb3duYW1lcyhjaXRuc3RlbW0xNClbOF0pLGxpc3QobmFtZT1yb3duYW1lcyhjaXRuc3RlbW0xNClbOV0pLGxpc3QobmFtZT1yb3duYW1lcyhjaXRuc3RlbW0xNClbMTBdKSxsaXN0KG5hbWU9Y29sbmFtZXMoY2l0bnN0ZW1tMTQpWzFdKSxsaXN0KG5hbWU9Y29sbmFtZXMoY2l0bnN0ZW1tMTQpWzJdKSxsaXN0KG5hbWU9Y29sbmFtZXMoY2l0bnN0ZW1tMTQpWzNdKSxsaXN0KG5hbWU9Y29sbmFtZXMoY2l0bnN0ZW1tMTQpWzRdKSxsaXN0KG5hbWU9Y29sbmFtZXMoY2l0bnN0ZW1tMTQpWzVdKSxsaXN0KG5hbWU9Y29sbmFtZXMoY2l0bnN0ZW1tMTQpWzZdKSxsaXN0KG5hbWU9Y29sbmFtZXMoY2l0bnN0ZW1tMTQpWzddKSxsaXN0KG5hbWU9Y29sbmFtZXMoY2l0bnN0ZW1tMTQpWzhdKSxsaXN0KG5hbWU9Y29sbmFtZXMoY2l0bnN0ZW1tMTQpWzldKSxsaXN0KG5hbWU9Y29sbmFtZXMoY2l0bnN0ZW1tMTQpWzEwXSksbGlzdChuYW1lPWNvbG5hbWVzKGNpdG5zdGVtbTE0KVsxMV0pLGxpc3QobmFtZT1jb2xuYW1lcyhjaXRuc3RlbW0xNClbMTJdKSxsaXN0KG5hbWU9Y29sbmFtZXMoY2l0bnN0ZW1tMTQpWzEzXSksbGlzdChuYW1lPWNvbG5hbWVzKGNpdG5zdGVtbTE0KVsxNF0pLGxpc3QobmFtZT1jb2xuYW1lcyhjaXRuc3RlbW0xNClbMTVdKSxsaXN0KG5hbWU9Y29sbmFtZXMoY2l0bnN0ZW1tMTQpWzE2XSksbGlzdChuYW1lPWNvbG5hbWVzKGNpdG5zdGVtbTE0KVsxN10pLGxpc3QobmFtZT1jb2xuYW1lcyhjaXRuc3RlbW0xNClbMThdKSxsaXN0KG5hbWU9Y29sbmFtZXMoY2l0bnN0ZW1tMTQpWzE5XSksbGlzdChuYW1lPWNvbG5hbWVzKGNpdG5zdGVtbTE0KVsyMF0pLGxpc3QobmFtZT1jb2xuYW1lcyhjaXRuc3RlbW0xNClbMjFdKSxsaXN0KG5hbWU9Y29sbmFtZXMoY2l0bnN0ZW1tMTQpWzIyXSksbGlzdChuYW1lPWNvbG5hbWVzKGNpdG5zdGVtbTE0KVsyM10pLGxpc3QobmFtZT1jb2xuYW1lcyhjaXRuc3RlbW0xNClbMjRdKSxsaXN0KG5hbWU9Y29sbmFtZXMoY2l0bnN0ZW1tMTQpWzI1XSkpLAppdGVtU3R5bGU9bGlzdChub3JtYWw9bGlzdChsYWJlbD1saXN0KHNob3c9VFJVRSkpKSwKbWF0cml4PWNpdG5zdGVtbTE0YykpKQplY2hhcnQoY2hvcmRjaXRuc3RlbSkKYGBgCiMjIyMjIHZpc3VhbGl6YXRpb24gIzMgTm9uLUNpdGl6ZW4gU1RFTQpgYGB7cn0KemVybzEwMTA8LW1hdHJpeCgwLDEwLDEwKQp6ZXJvMjUyNTwtbWF0cml4KDAsMjUsMjUpCm5jaXRzdGVtbTE0YzE8LWNiaW5kKHplcm8xMDEwLG5jaXRzdGVtbTE0KQpuY2l0c3RlbW0xNGMyPC1jYmluZCh0KG5jaXRzdGVtbTE0KSx6ZXJvMjUyNSkKbmNpdHN0ZW1tMTRjPC1yYmluZChuY2l0c3RlbW0xNGMxLG5jaXRzdGVtbTE0YzIpCmNob3JkbmNpdHN0ZW09bGlzdCh0aXRsZT1saXN0KHRleHQ9J25vbi1DaXRpemVuIFNURU0nLHN1YnRleHQ9J0Zyb20gSmF2YVNjcmlwdCcseD0ncmlnaHQnLHk9J2JvdHRvbScpLAp0b29sdGlwPWxpc3QodHJpZ2dlcj0naXRlbScsZm9ybWF0dGVyPUpTKCdmdW5jdGlvbihwYXJhbXMpewogICAgICAgICAgICAgICAgICAgICAgaWYgKHBhcmFtcy5pbmRpY2F0b3IyKSB7IC8vIGlzIGVkZ2UKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHBhcmFtcy52YWx1ZS53ZWlnaHQ7CiAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Ugey8vIGlzIG5vZGUKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHBhcmFtcy5uYW1lCiAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfScpKSwKdG9vbGJveD1saXN0KHNob3c9VFJVRSxmZWF0dXJlPWxpc3QocmVzdG9yZT1saXN0KHNob3c9VFJVRSksbWFnaWNUeXBlPWxpc3Qoc2hvdz1UUlVFLHR5cGU9YygnZm9yY2UnLCdjaG9yZCcpKSwKc2F2ZUFzSW1hZ2U9bGlzdChzaG93PVRSVUUpKSksCmxlZ2VuZD1saXN0KHg9J2xlZnQnLGRhdGE9Yyhyb3duYW1lcyhuY2l0c3RlbW0xNCksY29sbmFtZXMobmNpdHN0ZW1tMTQpKSksCnNlcmllcz1saXN0KGxpc3QodHlwZT0nY2hvcmQnLHNob3dTY2FsZT1GQUxTRSxzaG93U2NhbGVUZXh0PUZBTFNFLApkYXRhPWxpc3QobGlzdChuYW1lPXJvd25hbWVzKG5jaXRzdGVtbTE0KVsxXSksbGlzdChuYW1lPXJvd25hbWVzKG5jaXRzdGVtbTE0KVsyXSksbGlzdChuYW1lPXJvd25hbWVzKG5jaXRzdGVtbTE0KVszXSksbGlzdChuYW1lPXJvd25hbWVzKG5jaXRzdGVtbTE0KVs0XSksbGlzdChuYW1lPXJvd25hbWVzKG5jaXRzdGVtbTE0KVs1XSksbGlzdChuYW1lPXJvd25hbWVzKG5jaXRzdGVtbTE0KVs2XSksbGlzdChuYW1lPXJvd25hbWVzKG5jaXRzdGVtbTE0KVs3XSksbGlzdChuYW1lPXJvd25hbWVzKG5jaXRzdGVtbTE0KVs4XSksbGlzdChuYW1lPXJvd25hbWVzKG5jaXRzdGVtbTE0KVs5XSksbGlzdChuYW1lPXJvd25hbWVzKG5jaXRzdGVtbTE0KVsxMF0pLGxpc3QobmFtZT1jb2xuYW1lcyhuY2l0c3RlbW0xNClbMV0pLGxpc3QobmFtZT1jb2xuYW1lcyhuY2l0c3RlbW0xNClbMl0pLGxpc3QobmFtZT1jb2xuYW1lcyhuY2l0c3RlbW0xNClbM10pLGxpc3QobmFtZT1jb2xuYW1lcyhuY2l0c3RlbW0xNClbNF0pLGxpc3QobmFtZT1jb2xuYW1lcyhuY2l0c3RlbW0xNClbNV0pLGxpc3QobmFtZT1jb2xuYW1lcyhuY2l0c3RlbW0xNClbNl0pLGxpc3QobmFtZT1jb2xuYW1lcyhuY2l0c3RlbW0xNClbN10pLGxpc3QobmFtZT1jb2xuYW1lcyhuY2l0c3RlbW0xNClbOF0pLGxpc3QobmFtZT1jb2xuYW1lcyhuY2l0c3RlbW0xNClbOV0pLGxpc3QobmFtZT1jb2xuYW1lcyhuY2l0c3RlbW0xNClbMTBdKSxsaXN0KG5hbWU9Y29sbmFtZXMobmNpdHN0ZW1tMTQpWzExXSksbGlzdChuYW1lPWNvbG5hbWVzKG5jaXRzdGVtbTE0KVsxMl0pLGxpc3QobmFtZT1jb2xuYW1lcyhuY2l0c3RlbW0xNClbMTNdKSxsaXN0KG5hbWU9Y29sbmFtZXMobmNpdHN0ZW1tMTQpWzE0XSksbGlzdChuYW1lPWNvbG5hbWVzKG5jaXRzdGVtbTE0KVsxNV0pLGxpc3QobmFtZT1jb2xuYW1lcyhuY2l0c3RlbW0xNClbMTZdKSxsaXN0KG5hbWU9Y29sbmFtZXMobmNpdHN0ZW1tMTQpWzE3XSksbGlzdChuYW1lPWNvbG5hbWVzKG5jaXRzdGVtbTE0KVsxOF0pLGxpc3QobmFtZT1jb2xuYW1lcyhuY2l0c3RlbW0xNClbMTldKSxsaXN0KG5hbWU9Y29sbmFtZXMobmNpdHN0ZW1tMTQpWzIwXSksbGlzdChuYW1lPWNvbG5hbWVzKG5jaXRzdGVtbTE0KVsyMV0pLGxpc3QobmFtZT1jb2xuYW1lcyhuY2l0c3RlbW0xNClbMjJdKSxsaXN0KG5hbWU9Y29sbmFtZXMobmNpdHN0ZW1tMTQpWzIzXSksbGlzdChuYW1lPWNvbG5hbWVzKG5jaXRzdGVtbTE0KVsyNF0pLGxpc3QobmFtZT1jb2xuYW1lcyhuY2l0c3RlbW0xNClbMjVdKSksCml0ZW1TdHlsZT1saXN0KG5vcm1hbD1saXN0KGxhYmVsPWxpc3Qoc2hvdz1UUlVFKSkpLAptYXRyaXg9bmNpdHN0ZW1tMTRjKSkpCmVjaGFydChjaG9yZG5jaXRzdGVtKQpgYGAKIyMjIyMgdmlzdWFsaXphdGlvbiAjNCBOb24tQ2l0aXplbiBOb24tU1RFTQpgYGB7cn0KemVybzEwMTA8LW1hdHJpeCgwLDEwLDEwKQp6ZXJvMjUyNTwtbWF0cml4KDAsMjUsMjUpCm5jaXRuc3RlbW0xNGMxPC1jYmluZCh6ZXJvMTAxMCxuY2l0bnN0ZW1tMTQpCm5jaXRuc3RlbW0xNGMyPC1jYmluZCh0KG5jaXRuc3RlbW0xNCksemVybzI1MjUpCm5jaXRuc3RlbW0xNGM8LXJiaW5kKG5jaXRuc3RlbW0xNGMxLG5jaXRuc3RlbW0xNGMyKQpjaG9yZG5jaXRuc3RlbT1saXN0KHRpdGxlPWxpc3QodGV4dD0nbm9uLUNpdGl6ZW4gbm9uLVNURU0nLHN1YnRleHQ9J0Zyb20gSmF2YVNjcmlwdCcseD0ncmlnaHQnLHk9J2JvdHRvbScpLAp0b29sdGlwPWxpc3QodHJpZ2dlcj0naXRlbScsZm9ybWF0dGVyPUpTKCdmdW5jdGlvbihwYXJhbXMpewogICAgICAgICAgICAgICAgICAgICAgaWYgKHBhcmFtcy5pbmRpY2F0b3IyKSB7IC8vIGlzIGVkZ2UKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHBhcmFtcy52YWx1ZS53ZWlnaHQ7CiAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Ugey8vIGlzIG5vZGUKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHBhcmFtcy5uYW1lCiAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfScpKSwKdG9vbGJveD1saXN0KHNob3c9VFJVRSxmZWF0dXJlPWxpc3QocmVzdG9yZT1saXN0KHNob3c9VFJVRSksbWFnaWNUeXBlPWxpc3Qoc2hvdz1UUlVFLHR5cGU9YygnZm9yY2UnLCdjaG9yZCcpKSwKc2F2ZUFzSW1hZ2U9bGlzdChzaG93PVRSVUUpKSksCmxlZ2VuZD1saXN0KHg9J2xlZnQnLGRhdGE9Yyhyb3duYW1lcyhuY2l0bnN0ZW1tMTQpLGNvbG5hbWVzKG5jaXRuc3RlbW0xNCkpKSwKc2VyaWVzPWxpc3QobGlzdCh0eXBlPSdjaG9yZCcsc2hvd1NjYWxlPUZBTFNFLHNob3dTY2FsZVRleHQ9RkFMU0UsCmRhdGE9bGlzdChsaXN0KG5hbWU9cm93bmFtZXMobmNpdG5zdGVtbTE0KVsxXSksbGlzdChuYW1lPXJvd25hbWVzKG5jaXRuc3RlbW0xNClbMl0pLGxpc3QobmFtZT1yb3duYW1lcyhuY2l0bnN0ZW1tMTQpWzNdKSxsaXN0KG5hbWU9cm93bmFtZXMobmNpdG5zdGVtbTE0KVs0XSksbGlzdChuYW1lPXJvd25hbWVzKG5jaXRuc3RlbW0xNClbNV0pLGxpc3QobmFtZT1yb3duYW1lcyhuY2l0bnN0ZW1tMTQpWzZdKSxsaXN0KG5hbWU9cm93bmFtZXMobmNpdG5zdGVtbTE0KVs3XSksbGlzdChuYW1lPXJvd25hbWVzKG5jaXRuc3RlbW0xNClbOF0pLGxpc3QobmFtZT1yb3duYW1lcyhuY2l0bnN0ZW1tMTQpWzldKSxsaXN0KG5hbWU9cm93bmFtZXMobmNpdG5zdGVtbTE0KVsxMF0pLGxpc3QobmFtZT1jb2xuYW1lcyhuY2l0bnN0ZW1tMTQpWzFdKSxsaXN0KG5hbWU9Y29sbmFtZXMobmNpdG5zdGVtbTE0KVsyXSksbGlzdChuYW1lPWNvbG5hbWVzKG5jaXRuc3RlbW0xNClbM10pLGxpc3QobmFtZT1jb2xuYW1lcyhuY2l0bnN0ZW1tMTQpWzRdKSxsaXN0KG5hbWU9Y29sbmFtZXMobmNpdG5zdGVtbTE0KVs1XSksbGlzdChuYW1lPWNvbG5hbWVzKG5jaXRuc3RlbW0xNClbNl0pLGxpc3QobmFtZT1jb2xuYW1lcyhuY2l0bnN0ZW1tMTQpWzddKSxsaXN0KG5hbWU9Y29sbmFtZXMobmNpdG5zdGVtbTE0KVs4XSksbGlzdChuYW1lPWNvbG5hbWVzKG5jaXRuc3RlbW0xNClbOV0pLGxpc3QobmFtZT1jb2xuYW1lcyhuY2l0bnN0ZW1tMTQpWzEwXSksbGlzdChuYW1lPWNvbG5hbWVzKG5jaXRuc3RlbW0xNClbMTFdKSxsaXN0KG5hbWU9Y29sbmFtZXMobmNpdG5zdGVtbTE0KVsxMl0pLGxpc3QobmFtZT1jb2xuYW1lcyhuY2l0bnN0ZW1tMTQpWzEzXSksbGlzdChuYW1lPWNvbG5hbWVzKG5jaXRuc3RlbW0xNClbMTRdKSxsaXN0KG5hbWU9Y29sbmFtZXMobmNpdG5zdGVtbTE0KVsxNV0pLGxpc3QobmFtZT1jb2xuYW1lcyhuY2l0bnN0ZW1tMTQpWzE2XSksbGlzdChuYW1lPWNvbG5hbWVzKG5jaXRuc3RlbW0xNClbMTddKSxsaXN0KG5hbWU9Y29sbmFtZXMobmNpdG5zdGVtbTE0KVsxOF0pLGxpc3QobmFtZT1jb2xuYW1lcyhuY2l0bnN0ZW1tMTQpWzE5XSksbGlzdChuYW1lPWNvbG5hbWVzKG5jaXRuc3RlbW0xNClbMjBdKSxsaXN0KG5hbWU9Y29sbmFtZXMobmNpdG5zdGVtbTE0KVsyMV0pLGxpc3QobmFtZT1jb2xuYW1lcyhuY2l0bnN0ZW1tMTQpWzIyXSksbGlzdChuYW1lPWNvbG5hbWVzKG5jaXRuc3RlbW0xNClbMjNdKSxsaXN0KG5hbWU9Y29sbmFtZXMobmNpdG5zdGVtbTE0KVsyNF0pLGxpc3QobmFtZT1jb2xuYW1lcyhuY2l0bnN0ZW1tMTQpWzI1XSkpLAppdGVtU3R5bGU9bGlzdChub3JtYWw9bGlzdChsYWJlbD1saXN0KHNob3c9VFJVRSkpKSwKbWF0cml4PW5jaXRuc3RlbW0xNGMpKSkKZWNoYXJ0KGNob3JkbmNpdG5zdGVtKQpgYGAKCgojIFBhcnQgMi4gSW5mbHVlbmNlcyBvZiBTVEVNIHBvbGljeSBvbiBlbXBsb3llZXMKCiMjIyAqKjEuIE91ciBPYmplY3RpdmUqKgoKSW4gdGhpcyBwYXJ0IG9mIGFuYWx5c2lzLCB3ZSB3YW50IHRvIGtub3cgaG93IFNURU0gam9icyBoYXZlIGNoYW5nZWQgYWxvbmcgd2l0aCB0aGUgYW5ub3VuY2VtZW50IG9mIHRoZSBTVEVNIHBvbGljeS4gVHdvIGRhdGEgc2V0cyBhcmUgYmVpbmcgdXNlZDogZGF0YSBvZiAyMDA3LCB3aGljaCBpcyB0aGUgbGFzdCB5ZWFyIGJlZm9yZSBTVEVNIHBvbGljeSwgYW5kIGRhdGEgb2YgMjAxNCwgdGhlIGxhdGVzdCBvYnRhaW5hYmxlIHVuZGVyLVNURU0tcG9saWN5IGRhdGEuIEZvciBlYWNoIGRhdGEgc2V0LCB3ZSBjYXRlZ29yaXplIG91ciBkYXRhIGludG8gdHdvIGNsYXNzZXM6IFNURU0tam9iIGRhdGEgYW5kIG5vbi1TVEVNLWpvYiBkYXRhLiBCeSBkb2luZyB0aGUgc2VwYXJhdGlvbnMsIHdlIGNhbiBsb29rIGF0IHRoZSBkaWZmZXJlbmNlcyBvZiBTVEVNIGFuZCBub24tU1RFTSBqb2JzIGJlZm9yZSBhbmQgYWZ0ZXIgU1RFTSBwb2xpY3kgd2VudCBvdXQuCgojIyMgKioyLiBPdXIgQ29uY2VybnMqKgoKMS4gV2lsbCB0aGUgU1RFTS9ub24tU1RFTSBqb2IgYWxsb2NhdGlvbiBjaGFuZ2U/CgoyLiBBbW9uZyBTVEVNL25vbi1TVEVNIGpvYnMsIHdpbGwgZ2VuZGVyIHByb3BvcnRpb24gYW5kIGNsYXNzIG9mIHdvcmsgYmUgaW5mbHVlbmNlZCBieSB0aGUgU1RFTSBwb2xpY3k/CgozLiBIb3cgZGlkIHRoZSB3b3JraW5nIGNvbmRpdGlvbnMsIHN1Y2ggYXMgd2FnZSBhbmQgd29ya2luZyBob3VycyBjaGFuZ2U/Cgo0LiBXaWxsIHRoZSBTVEVNIHBvbGljeSBmdXJ0aGVyIGluZmx1ZW5jZSBwZW9wbGUncyBpbW1pZ3JhdGlvbiBiZWhhdmlvcj8KCiMjIyAqKjMuIE91ciBGaW5kaW5ncyoqCgpUaGUgZmlyc3QgdGhpbmcgd2Ugc3R1ZGllZCBpcyB3aGV0aGVyIHRoZSBTVEVNL25vbi1TVEVNIGpvYiBhbGxvY2F0aW9uIGhhcyBjaGFuZ2VkIGdlb2dyYXBoaWNhbGx5LgpBY2NvcmRpbmcgdG8gdGhlIGZpcnN0IHR3byBmaWd1cmVzLCB3ZSBjYW4gc2VlIHRoYXQgdGhlIGFsbG9jYXRpb24gb2Ygbm9uLVNURU0gam9icyBiYXJlbHkgY2hhbmdlZCBhZnRlciBTVEVNIHBvbGljeSB3ZW50IG91dC4KQWNjb3JkaW5nIHRvIHRoZSBsYXN0IHR3byBmaWd1cmVzLCB3ZSBzZWUgZm9yIFNURU0gam9icywgc29tZXRoaW5nIGhhcHBlbmVkIG9uIHRoZSBlYXN0IGNvYXN0LgpgYGB7cn0KbGlicmFyeShkYXRhLnRhYmxlKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoZm1zYikKbGlicmFyeShjaG9yb3BsZXRocikKbGlicmFyeShjaG9yb3BsZXRock1hcHMpCgojIHJlYWQgZGF0YQpjb2xzIDwtIGMoIldBR1AiLCAiU1QiLCAiQUdFUCIsICJFU1IiLCAiQ0lUIiwgIllPRVAiLCAiQ09XIiwgIlNFWCIgLCAiV0tIUCIsIldLVyIsIlNPQ1AiLCJQT1dTUCIsIlBPVlBJUCIsIlNDSEwiKQoKYmVmb3JlX2RhdGExMTwtZnJlYWQoIi9Vc2Vycy9ZYXFpbmdYaWUvRGVza3RvcC9BcHBsaWVkIERhdGEgU2NpZW5jZS9XZWVrMS9jc3ZfcHVzKDIwMDcpL3NzMDdwdXNhLmNzdiIsIHNlbGVjdD1jb2xzKQpiZWZvcmVfZGF0YTEyPC1mcmVhZCgiL1VzZXJzL1lhcWluZ1hpZS9EZXNrdG9wL0FwcGxpZWQgRGF0YSBTY2llbmNlL1dlZWsxL2Nzdl9wdXMoMjAwNykvc3MwN3B1c2EuY3N2Iiwgc2VsZWN0PWMoMTYwOjIzOSkpCmJlZm9yZV9kYXRhMjE8LWZyZWFkKCIvVXNlcnMvWWFxaW5nWGllL0Rlc2t0b3AvQXBwbGllZCBEYXRhIFNjaWVuY2UvV2VlazEvY3N2X3B1cygyMDA3KS9zczA3cHVzYi5jc3YiLCBzZWxlY3Q9Y29scykKYmVmb3JlX2RhdGEyMjwtZnJlYWQoIi9Vc2Vycy9ZYXFpbmdYaWUvRGVza3RvcC9BcHBsaWVkIERhdGEgU2NpZW5jZS9XZWVrMS9jc3ZfcHVzKDIwMDcpL3NzMDdwdXNiLmNzdiIsIHNlbGVjdD1jKDE2MDoyMzkpKQpiZWZvcmVfZGF0YTEgPC0gY2JpbmQoYmVmb3JlX2RhdGExMSwgYmVmb3JlX2RhdGExMikKYmVmb3JlX2RhdGEyIDwtIGNiaW5kKGJlZm9yZV9kYXRhMjEsIGJlZm9yZV9kYXRhMjIpCmJlZm9yZV9kYXRhPC0gc3Vic2V0KHJiaW5kKGJlZm9yZV9kYXRhMSwgYmVmb3JlX2RhdGEyKSkKCmFmdGVyX2RhdGExMTwtZnJlYWQoIi9Vc2Vycy9ZYXFpbmdYaWUvRGVza3RvcC9BcHBsaWVkIERhdGEgU2NpZW5jZS9XZWVrMS9jc3ZfcHVzL3NzMTRwdXNhLmNzdiIsIHNlbGVjdD1jb2xzKQphZnRlcl9kYXRhMTI8LWZyZWFkKCIvVXNlcnMvWWFxaW5nWGllL0Rlc2t0b3AvQXBwbGllZCBEYXRhIFNjaWVuY2UvV2VlazEvY3N2X3B1cy9zczE0cHVzYS5jc3YiLCBzZWxlY3Q9YygyMDU6Mjg0KSkKYWZ0ZXJfZGF0YTIxPC1mcmVhZCgiL1VzZXJzL1lhcWluZ1hpZS9EZXNrdG9wL0FwcGxpZWQgRGF0YSBTY2llbmNlL1dlZWsxL2Nzdl9wdXMvc3MxNHB1c2IuY3N2Iiwgc2VsZWN0PWNvbHMpCmFmdGVyX2RhdGEyMjwtZnJlYWQoIi9Vc2Vycy9ZYXFpbmdYaWUvRGVza3RvcC9BcHBsaWVkIERhdGEgU2NpZW5jZS9XZWVrMS9jc3ZfcHVzL3NzMTRwdXNiLmNzdiIsIHNlbGVjdD1jKDIwNToyODQpKQphZnRlcl9kYXRhMSA8LSBjYmluZChhZnRlcl9kYXRhMTEsIGFmdGVyX2RhdGExMikKYWZ0ZXJfZGF0YTIgPC0gY2JpbmQoYWZ0ZXJfZGF0YTIxLCBhZnRlcl9kYXRhMjIpCmFmdGVyX2RhdGE8LSBzdWJzZXQocmJpbmQoYWZ0ZXJfZGF0YTEsIGFmdGVyX2RhdGEyKSkKCiNmaWx0ZXIgZGF0YTogb25seSBwZW9wbGUgY3VycmVubHR5IGVtcGxveWVlZCBpbiBVUwpiZWZvcmVfZGF0YTwtYmVmb3JlX2RhdGFbIShiZWZvcmVfZGF0YSRFU1IgJWluJSBjKDMsNixOQSkpXQpiZWZvcmVfZGF0YTwtYmVmb3JlX2RhdGFbYmVmb3JlX2RhdGEkUE9XU1AgPj0gMSAmIGJlZm9yZV9kYXRhJFBPV1NQIDw9IDU2XQphZnRlcl9kYXRhPC1hZnRlcl9kYXRhWyEoYWZ0ZXJfZGF0YSRFU1IgJWluJSBjKDMsNixOQSkpXQphZnRlcl9kYXRhPC1hZnRlcl9kYXRhW2FmdGVyX2RhdGEkUE9XU1AgPj0gMSAmIGFmdGVyX2RhdGEkUE9XU1AgPD0gNTZdCgojIGpvYiBjb2RlIGZvciBTVEVNIG9jY3VwYXRpb25zCiMgc291cmNlOiBodHRwOi8vd3d3LmJscy5nb3Yvc29jL0F0dGFjaG1lbnRfQ19TVEVNLnBkZgpiZWZvcmVfc3RlbV9qb2JfY29kZXMgPSBjKCcxMTMwMjEnLCcxMTkwNDEnLCcxMTkxMTEnLCcxMTkxMjEnLCcxNTEwMjEnLCcxNTEwMzAnLCcxNTEwNDEnLCcxNTEwNjEnLCcxNTEwNzEnLCcxNTEwODEnLCcxNTEwWFgnLCcxNTIwMTEnLCcxNTIwMzEnLCcxNTIwWFgnLCcxNzEwMTAnLCcxNzEwMjAnLCcxNzIwMTEnLCcxNzIwNDEnLCcxNzIwNTEnLCcxNzIwNjEnLCcxNzIwNzAnLCcxNzIwODEnLCcxNzIwWFgnLCcxNzIxMTAnLCcxNzIxMjEnLCcxNzIxMzEnLCcxNzIxNDEnLCcxNzIxWFgnLCcxNzIxWVknLCcxNzMwMTAnLCcxNzMwMjAnLCcxNzMwMzEnLCcxOTEwMTAnLCcxOTEwMjAnLCcxOTEwMzAnLCcxOTEwNDAnLCcxOTIwMTAnLCcxOTIwMjEnLCcxOTIwMzAnLCcxOTIwNDAnLCcxOTIwOTknLCcxOTMwMTEnLCcxOTMwMjAnLCcxOTMwMzAnLCcxOTMwNTEnLCcxOTMwWFgnLCcxOTQwMTEnLCcxOTQwMjEnLCcxOTQwMzEnLCcxOTQwNDEnLCcxOTQwWFgnLCcyNTQwMTAnLCcyOTEwMTEnLCcyOTEwMjAnLCcyOTEwMzEnLCcyOTEwNDEnLCcyOTEwNTEnLCcyOTEwNjAnLCcyOTEwNzEnLCcyOTEwODEnLCcyOTExMTEnLCcyOTExMjEnLCcyOTExMjInLCcyOTExMjMnLCcyOTExMjQnLCcyOTExMjUnLCcyOTExMjYnLCcyOTExMjcnLCcyOTExMjknLCcyOTExMzEnLCcyOTExOTknLCcyOTIwMTAnLCcyOTIwMjEnLCcyOTIwMzAnLCcyOTIwNDEnLCcyOTIwNTAnLCcyOTIwNjEnLCcyOTIwNzEnLCcyOTIwODEnLCcyOTIwOTAnLCcyOTkwMDAnLCc0MTQwMTAnLCc0MTkwMzEnKQphZnRlcl9zdGVtX2pvYl9jb2RlcyA9IGMoJzExMzAyMScsJzExOTA0MScsJzExOTEyMScsJzE1MTExMScsJzE1MTEyMScsJzE1MTEyMicsJzE1MTEzMScsJzE1MTEzMicsJzE1MTEzMycsJzE1MTEzNCcsJzE1MTE0MScsJzE1MTE0MicsJzE1MTE0MycsJzE1MTE1MScsJzE1MTE1MicsJzE1MTE5OScsJzE1MjAxMScsJzE1MjAyMScsJzE1MjAzMScsJzE1MjA0MScsJzE1MjA5OScsJzE3MTAyMScsJzE3MTAyMicsJzE3MjAxMScsJzE3MjAyMScsJzE3MjAzMScsJzE3MjA0MScsJzE3MjA1MScsJzE3MjA2MScsJzE3MjA3MScsJzE3MjA3MicsJzE3MjA4MScsJzE3MjExMScsJzE3MjExMicsJzE3MjEyMScsJzE3MjEzMScsJzE3MjE0MScsJzE3MjE1MScsJzE3MjE2MScsJzE3MjE3MScsJzE3MjE5OScsJzE3MzAxMicsJzE3MzAxMycsJzE3MzAxOScsJzE3MzAyMScsJzE3MzAyMicsJzE3MzAyMycsJzE3MzAyNCcsJzE3MzAyNScsJzE3MzAyNicsJzE3MzAyNycsJzE3MzAyOScsJzE3MzAzMScsJzE5MTAxMScsJzE5MTAxMicsJzE5MTAxMicsJzE5MTAyMScsJzE5MTAyMicsJzE5MTAyMycsJzE5MTAyOScsJzE5MTAzMScsJzE5MTAzMicsJzE5MTA0MScsJzE5MTA0MicsJzE5MTA5OScsJzE5MjAxMScsJzE5MjAxMicsJzE5MjAyMScsJzE5MjAzMScsJzE5MjAzMicsJzE5MjA0MScsJzE5MjA0MicsJzE5MjA0MycsJzE5MjA5OScsJzE5NDAxMScsJzE5NDAyMScsJzE5NDAzMScsJzE5NDA0MScsJzE5NDA1MScsJzE5NDA5MScsJzE5NDA5MicsJzE5NDA5MycsJzI1MTAyMScsJzI1MTAyMicsJzI1MTAzMicsJzI1MTA0MScsJzI1MTA0MicsJzI1MTA0MycsJzI1MTA1MScsJzI1MTA1MicsJzI1MTA1MycsJzI1MTA1NCcsJzQxNDAxMScsJzQxOTAzMScpCgojIGNhdGVnb3JpemUgam9iIGludG8gc3RlbSBhbmQgbm9uLXN0ZW0KYmVmb3JlX2RhdGEkU09DUFshKGJlZm9yZV9kYXRhJFNPQ1AgJWluJSBiZWZvcmVfc3RlbV9qb2JfY29kZXMpICYgKGJlZm9yZV9kYXRhJFNPQ1AhPSIiKV0gPC0gIk5PTi1TVEVNIgpiZWZvcmVfZGF0YSRTT0NQW2JlZm9yZV9kYXRhJFNPQ1AgJWluJSBiZWZvcmVfc3RlbV9qb2JfY29kZXNdIDwtICJTVEVNIgphZnRlcl9kYXRhJFNPQ1BbIShhZnRlcl9kYXRhJFNPQ1AgJWluJSBhZnRlcl9zdGVtX2pvYl9jb2RlcykgJiAoYWZ0ZXJfZGF0YSRTT0NQIT0iIildIDwtICJOT04tU1RFTSIKYWZ0ZXJfZGF0YSRTT0NQW2FmdGVyX2RhdGEkU09DUCAlaW4lIGFmdGVyX3N0ZW1fam9iX2NvZGVzXSA8LSAiU1RFTSIKCiMgcmVuYW1lIGdlbmRlcgpiZWZvcmVfZGF0YSRTRVhbYmVmb3JlX2RhdGEkU0VYID09IDFdIDwtICJNYWxlIgpiZWZvcmVfZGF0YSRTRVhbYmVmb3JlX2RhdGEkU0VYID09IDJdIDwtICJGZW1hbGUiCmFmdGVyX2RhdGEkU0VYW2FmdGVyX2RhdGEkU0VYID09IDFdIDwtICJNYWxlIgphZnRlcl9kYXRhJFNFWFthZnRlcl9kYXRhJFNFWCA9PSAyXSA8LSAiRmVtYWxlIgoKIyByZW5hbWUgY2xhc3Mgb2Ygd29ya2VyCmJlZm9yZV9kYXRhJENPV1tiZWZvcmVfZGF0YSRDT1cgPT0gMV0gPC0gIkZvci1wcm9maXQgQ29tcGFueSIKYmVmb3JlX2RhdGEkQ09XW2JlZm9yZV9kYXRhJENPVyA9PSAyXSA8LSAiTm90LWZvci1wcm9maXQgT3JnYW5pemF0aW9uIgpiZWZvcmVfZGF0YSRDT1dbYmVmb3JlX2RhdGEkQ09XID09IDNdIDwtICJMb2NhbCBHb3Zlcm5tZW50IgpiZWZvcmVfZGF0YSRDT1dbYmVmb3JlX2RhdGEkQ09XID09IDRdIDwtICJTdGF0ZSBHb3Zlcm5tZW50IgpiZWZvcmVfZGF0YSRDT1dbYmVmb3JlX2RhdGEkQ09XID09IDVdIDwtICJGZWRlcmFsIEdvdmVybm1lbnQiCmJlZm9yZV9kYXRhJENPV1tiZWZvcmVfZGF0YSRDT1cgPT0gNl0gPC0gIlNlbGYtZW1wbG95ZWVkICYgTm90IEluY29ycG9yYXRlZCIKYmVmb3JlX2RhdGEkQ09XW2JlZm9yZV9kYXRhJENPVyA9PSA3XSA8LSAiU2VsZi1lbXBsb3llZWQgJiBJbmNvcnBvcmF0ZWQiCmJlZm9yZV9kYXRhJENPV1tiZWZvcmVfZGF0YSRDT1cgPT0gOF0gPC0gIkZhbWlseSBCdXNpbmVzcyIKYWZ0ZXJfZGF0YSRDT1dbYWZ0ZXJfZGF0YSRDT1cgPT0gMV0gPC0gIkZvci1wcm9maXQgQ29tcGFueSIKYWZ0ZXJfZGF0YSRDT1dbYWZ0ZXJfZGF0YSRDT1cgPT0gMl0gPC0gIk5vdC1mb3ItcHJvZml0IE9yZ2FuaXphdGlvbiIKYWZ0ZXJfZGF0YSRDT1dbYWZ0ZXJfZGF0YSRDT1cgPT0gM10gPC0gIkxvY2FsIEdvdmVybm1lbnQiCmFmdGVyX2RhdGEkQ09XW2FmdGVyX2RhdGEkQ09XID09IDRdIDwtICJTdGF0ZSBHb3Zlcm5tZW50IgphZnRlcl9kYXRhJENPV1thZnRlcl9kYXRhJENPVyA9PSA1XSA8LSAiRmVkZXJhbCBHb3Zlcm5tZW50IgphZnRlcl9kYXRhJENPV1thZnRlcl9kYXRhJENPVyA9PSA2XSA8LSAiU2VsZi1lbXBsb3llZWQgJiBOb3QgSW5jb3Jwb3JhdGVkIgphZnRlcl9kYXRhJENPV1thZnRlcl9kYXRhJENPVyA9PSA3XSA8LSAiU2VsZi1lbXBsb3llZWQgJiBJbmNvcnBvcmF0ZWQiCmFmdGVyX2RhdGEkQ09XW2FmdGVyX2RhdGEkQ09XID09IDhdIDwtICJGYW1pbHkgQnVzaW5lc3MiCgojIHJlY29kZSBudW1iZXIgb2Ygd2Vla3Mgd29ya2VkIGluIHRoZSBwYXN0IHllYXIKYWZ0ZXJfZGF0YSRXS1dbYWZ0ZXJfZGF0YSRXS1c9PTFdIDwtIDUxCmFmdGVyX2RhdGEkV0tXW2FmdGVyX2RhdGEkV0tXPT0yXSA8LSA0OC41CmFmdGVyX2RhdGEkV0tXW2FmdGVyX2RhdGEkV0tXPT0zXSA8LSA0My41CmFmdGVyX2RhdGEkV0tXW2FmdGVyX2RhdGEkV0tXPT00XSA8LSAzMwphZnRlcl9kYXRhJFdLV1thZnRlcl9kYXRhJFdLVz09NV0gPC0gMjAKYWZ0ZXJfZGF0YSRXS1dbYWZ0ZXJfZGF0YSRXS1c9PTZdIDwtIDcKYGBgCgojIyMjICgxKSBKb2IgQWxsb2NhdGlvbiBpbiBVUwoKYGBge3J9CiMgcGxvdHRpbmcKIyAxIFBPV1NQLXN0ZW0vbm9uc3RlbS1iZWZvcmUvYWZ0ZXIgIE1BUApiZWZvcmVfc3RlbSA8LSBiZWZvcmVfZGF0YVtiZWZvcmVfZGF0YSRTT0NQID09ICdTVEVNJ10KYmVmb3JlX3N0YXRlX3N0ZW0gPC0gc3Vic2V0KGJlZm9yZV9zdGVtLCBzZWxlY3Q9YygiU1QiLCJQT1dTUCIpKQpiZWZvcmVfbm9uc3RlbSA8LSBiZWZvcmVfZGF0YVtiZWZvcmVfZGF0YSRTT0NQID09ICdOT04tU1RFTSddCmJlZm9yZV9zdGF0ZV9ub25zdGVtIDwtIHN1YnNldChiZWZvcmVfbm9uc3RlbSwgc2VsZWN0PWMoIlNUIiwiUE9XU1AiKSkKYWZ0ZXJfc3RlbSA8LSBhZnRlcl9kYXRhW2FmdGVyX2RhdGEkU09DUCA9PSAnU1RFTSddCmFmdGVyX3N0YXRlX3N0ZW0gPC0gc3Vic2V0KGFmdGVyX3N0ZW0sIHNlbGVjdD1jKCJTVCIsIlBPV1NQIikpCmFmdGVyX25vbnN0ZW0gPC0gYWZ0ZXJfZGF0YVthZnRlcl9kYXRhJFNPQ1AgPT0gJ05PTi1TVEVNJ10KYWZ0ZXJfc3RhdGVfbm9uc3RlbSA8LSBzdWJzZXQoYWZ0ZXJfbm9uc3RlbSwgc2VsZWN0PWMoIlNUIiwiUE9XU1AiKSkKZGF0YSgic3RhdGUucmVnaW9ucyIpCnN0YXRlbmFtZXMgPC0gZGF0YS5mcmFtZShjYmluZChzdGF0ZS5yZWdpb25zWywxXSxzdGF0ZS5yZWdpb25zWywzXSkpCm5hbWVzKHN0YXRlbmFtZXMpIDwtIGMoJ3JlZ2lvbicsICdyZWdpb25fY29kZScpCgpnZXRzdGF0ZSA8LSBmdW5jdGlvbih2ZWN0b3IpewogIHRlbXAgPC0gZGF0YS5mcmFtZSh2ZWN0b3IpCiAgbmFtZXModGVtcCkgPC0gYygicmVnaW9uX2NvZGUiKQogIG5ld19kYXRhZnJhbWUgPC0gbWVyZ2UodGVtcCxzdGF0ZW5hbWVzLCBieS54PSJyZWdpb25fY29kZSIsIGJ5Lnk9J3JlZ2lvbl9jb2RlJykKICBuZXdfZGF0YWZyYW1lIDwtIHRhYmxlKG5ld19kYXRhZnJhbWUkcmVnaW9uKQogIG5ld19kYXRhZnJhbWUgPC0gZGF0YS5mcmFtZShuZXdfZGF0YWZyYW1lKQogIG5hbWVzKG5ld19kYXRhZnJhbWUpIDwtIGMoJ3JlZ2lvbicsJ3ZhbHVlJykKICByZXR1cm4obmV3X2RhdGFmcmFtZSkKfQoKYmVmb3JlX3N0ZW1fU1QgPC0gZ2V0c3RhdGUoYmVmb3JlX3N0YXRlX3N0ZW0kU1QpCmJlZm9yZV9zdGVtX1BPVyA8LSBnZXRzdGF0ZShiZWZvcmVfc3RhdGVfc3RlbSRQT1dTUCkKYmVmb3JlX25vbnN0ZW1fU1QgPC0gZ2V0c3RhdGUoYmVmb3JlX3N0YXRlX25vbnN0ZW0kU1QpCmJlZm9yZV9ub25zdGVtX1BPVyA8LSBnZXRzdGF0ZShiZWZvcmVfc3RhdGVfbm9uc3RlbSRQT1dTUCkKYWZ0ZXJfc3RlbV9TVCA8LSBnZXRzdGF0ZShhZnRlcl9zdGF0ZV9zdGVtJFNUKQphZnRlcl9zdGVtX1BPVyA8LSBnZXRzdGF0ZShhZnRlcl9zdGF0ZV9zdGVtJFBPV1NQKQphZnRlcl9ub25zdGVtX1NUIDwtIGdldHN0YXRlKGFmdGVyX3N0YXRlX25vbnN0ZW0kU1QpCmFmdGVyX25vbnN0ZW1fUE9XIDwtIGdldHN0YXRlKGFmdGVyX3N0YXRlX25vbnN0ZW0kUE9XU1ApCgpzdGF0ZV9jaG9yb3BsZXRoKGJlZm9yZV9ub25zdGVtX1BPVywKICAgICAgICAgICAgICAgICB0aXRsZSAgICAgID0gIkJlZm9yZSBTVEVNIFBvbGljeTogTk9OLVNURU0gSm9iIEFsbG9jYXRpb24iLAogICAgICAgICAgICAgICAgIGxlZ2VuZCAgICAgPSAiTnVtYmVyIG9mIE9jY3VwYXRpb25zIiwKICAgICAgICAgICAgICAgICBudW1fY29sb3JzID0gMSkKc3RhdGVfY2hvcm9wbGV0aChhZnRlcl9ub25zdGVtX1BPVywKICAgICAgICAgICAgICAgICB0aXRsZSAgICAgID0gIkFmdGVyIFNURU0gUG9saWN5OiBOT04tU1RFTSBKb2IgQWxsb2NhdGlvbiIsCiAgICAgICAgICAgICAgICAgbGVnZW5kICAgICA9ICJOdW1iZXIgb2YgT2NjdXBhdGlvbnMiLAogICAgICAgICAgICAgICAgIG51bV9jb2xvcnMgPSAxKQpzdGF0ZV9jaG9yb3BsZXRoKGJlZm9yZV9zdGVtX1BPVywKICAgICAgICAgICAgICAgICB0aXRsZSAgICAgID0gIkJlZm9yZSBTVEVNIFBvbGljeTogU1RFTSBKb2IgQWxsb2NhdGlvbiIsCiAgICAgICAgICAgICAgICAgbGVnZW5kICAgICA9ICJOdW1iZXIgb2YgT2NjdXBhdGlvbnMiLAogICAgICAgICAgICAgICAgIG51bV9jb2xvcnMgPSAxKQpzdGF0ZV9jaG9yb3BsZXRoKGFmdGVyX3N0ZW1fUE9XLAogICAgICAgICAgICAgICAgIHRpdGxlICAgICAgPSAiQWZ0ZXIgU1RFTSBQb2xpY3k6IFNURU0gSm9iIEFsbG9jYXRpb24iLAogICAgICAgICAgICAgICAgIGxlZ2VuZCAgICAgPSAiTnVtYmVyIG9mIE9jY3VwYXRpb25zIiwKICAgICAgICAgICAgICAgICBudW1fY29sb3JzID0gMSkKYGBgCgoKSWYgd2UgdGFrZSBhIGNsb3NlciBsb29rIGF0IHRoZXNlIHN0YXRlcywgd2UgY2FuIHNlZSByZWxldmFudCBqb2JzIGluIE5ZIGFuZCBGTCB0ZW5kZWQgdG8gZGlmZnVzZSB0b3dhcmRzIG5laWdoYm9yaW5nIHN0YXRlcywgYW1vbmcgd2hpY2gsIFZpcmdpbmlhIGhhcyB0aGUgbW9zdCBzaWduaWZpY2FudCBpbmNyZWFzZSBpbiB0ZXJtcyBvZiB0aGUgYW1vdW50IG9mIFNURU0gam9icy4KYGBge3J9CnN0YXRlX2Nob3JvcGxldGgoYmVmb3JlX3N0ZW1fUE9XLAogICAgICAgICAgICAgICAgIHRpdGxlICAgICAgPSAiQmVmb3JlIFNURU0gUG9saWN5OiBTVEVNIEpvYiBBbGxvY2F0aW9uIiwKICAgICAgICAgICAgICAgICBsZWdlbmQgICAgID0gIk51bWJlciBvZiBPY2N1cGF0aW9ucyIsCiAgICAgICAgICAgICAgICAgbnVtX2NvbG9ycyA9IDEsCiAgICAgICAgICAgICAgICAgem9vbSA9IGMoIm5ldyB5b3JrIiwicGVubnN5bHZhbmlhIiwidmlyZ2luaWEiLCJvaGlvIiwibm9ydGggY2Fyb2xpbmEiLCJzb3V0aCBjYXJvbGluYSIsImdlb3JnaWEiLCJmbG9yaWRhIikpCnN0YXRlX2Nob3JvcGxldGgoYWZ0ZXJfc3RlbV9QT1csCiAgICAgICAgICAgICAgICAgdGl0bGUgICAgICA9ICJBZnRlciBTVEVNIFBvbGljeTogU1RFTSBKb2IgQWxsb2NhdGlvbiIsCiAgICAgICAgICAgICAgICAgbGVnZW5kICAgICA9ICJOdW1iZXIgb2YgT2NjdXBhdGlvbnMiLAogICAgICAgICAgICAgICAgIG51bV9jb2xvcnMgPSAxLAogICAgICAgICAgICAgICAgIHpvb20gPSBjKCJuZXcgeW9yayIsInBlbm5zeWx2YW5pYSIsInZpcmdpbmlhIiwib2hpbyIsIm5vcnRoIGNhcm9saW5hIiwic291dGggY2Fyb2xpbmEiLCJnZW9yZ2lhIiwiZmxvcmlkYSIpKQoKYGBgCkluIGdlbmVyYWwsIHRoZSBzdGF0ZSBhbGxvY2F0aW9uIG9mIGpvYnMgZGlkbid0IGNoYW5nZSBkcmFtYXRpY2FsbHkgYWZ0ZXIgdGhlIFNURU0gcG9saWN5IHdlbnQgb3V0LiBJdCBjb3VsZCBiZSBwbGF1c2libGUgc2luY2UgU1RFTSBwb2xpY3kgaXMgaW4gZWZmZWN0IGZvciBmb3JlaWduIHN0dWRlbnRzIHdoaWxlIHRoZSBqb2IgYWxsb2NhdGlvbiBkZXBlbmRzIG1vcmUgb24gdGhlIGxvY2F0aW9uYWwgY2hvaWNlcyBvZiBkaWZmZXJlbnQgY29tcGFuaWVzLgoKCiMjIyMgKDIpIFdvcmtpbmcgQ29uZGl0aW9uczogV2hhdCB0byBQYXkgYW5kIFdoYXQgdG8gR2V0CgpUaGUgc2Vjb25kIGZpZ3VyZSB3ZSBnb3QgaXMgYSByYWRhciBjaGFydCBjb25zaWRlcmluZyBpbmNvbWUsIHdvcmtpbmcgaG91cnMvd2Vla3MsIGRlZ3JlZSBsZXZlbCBhbmQgaW5jb21lLXRvLXBvdmVydHkgaW5kZXguCgpTVEVNIGpvYnMgdXNlZCB0byBiZSB0aGUga2luZCBvZiBqb2JzIGluIHdoaWNoIHlvdSBuZWVkIHRvIHBheSBtb3JlIGluIG9yZGVyIHRvIGdldCBtb3JlLiBUaGUgZ29vZCB0aGluZyB3YXMsIHlvdSBkaWRuJ3QgbmVlZCB0byBoYXZlIGFuIGFkdmFuY2VkIGRlZ3JlZSB0byBnZXQgc3VjaCBraW5kIG9mIGpvYnMuCkhvd2V2ZXJtIGFmdGVyIFNURU0gcG9saWN5IHdlbnQgb3V0LCB0aGUgcmVxdWlyZW1lbnQgb2YgZGVncmVlIGluIFNURU0gam9icyByYWlzZWQgc2hhcnBseS4gVGhvdWdoIHRoZSBjaGFuZ2UgaW4gbm9uLVNURU0gam9icyBpcyBncmVhdCB0b28sIFNURU0gam9icyBhcmUgc3RpbGwgdGhlIGdyb3VwIHdoaWNoIHJlcXVpcmVzIHRoZSBoaWdoZXN0IGF2ZXJhZ2UgZGVncmVlIGF0dGFpbm1lbnQuCgpXZSBjYW4gYWxzbyByZWFkIG1vcmUgaW5mb3JtYXRpb24gZnJvbSB0aGlzIGZpZ3VyZSwgc3VjaCBhcywgY3VycmVudGx5LCB0aGUgYmV0dGVyIGluY29tZS9kZWdyZWUgcGVyZm9ybWFuY2UgYXBwZWFycyB0byBTVEVNIGpvYnMgaW5zdGVhZCBvZiBub24tU1RFTSBqb2JzIGFuZCB0aGUgZ2FwIGlzIHF1aXRlIG9idmlvdXMuIEhvd2V2ZXIsIHNwZWFraW5nIG9mIGluY29tZS93b3JraW5nIGhvdXJzLCBub24tU1RFTSBqb2IgY291bGQgYmUgYSBiZXR0ZXIgY2hvaWNlLgpgYGB7cn0KIyAyIHdhZ2Umd2tocCZ3a3cmcG92cGlwJnNjaGwtc3RlbS9ub25zdGVtLWJlZm9yZS9hZnRlcgojIHN1cnZleSB3ZWlnaHQKbGlicmFyeShzdXJ2ZXkpCiNkZl9iZWZvcmU8LXN2cmVwZGVzaWduKHZhcmlhYmxlcz1iZWZvcmVfZGF0YVssMToxNl0sIAojICAgICAgICAgICAgICAgICByZXB3ZWlnaHRzPWJlZm9yZV9kYXRhWywxNzo4Nl0sIHR5cGU9IkJSUiIsY29tYmluZWQud2VpZ2h0cz1UUlVFLAojICAgICAgICAgICAgICAgICB3ZWlnaHRzPWJlZm9yZV9kYXRhJFBXR1RQKQojc3VtbWFyeShkZl9iZWZvcmUpCiNzdnltZWFuKH4gV0FHUCxkZl9iZWZvcmUsIG5hLnJtID0gVCkKI2RmX2FmdGVyPC1zdnJlcGRlc2lnbih2YXJpYWJsZXM9YWZ0ZXJfZGF0YVssMToxNl0sIAojICAgICAgICAgICAgICAgICAgICAgICByZXB3ZWlnaHRzPWFmdGVyX2RhdGFbLDE3Ojg2XSwgdHlwZT0iQlJSIixjb21iaW5lZC53ZWlnaHRzPVRSVUUsCiMgICAgICAgICAgICAgICAgICAgICAgIHdlaWdodHM9YWZ0ZXJfZGF0YSRQV0dUUCkKI3N1bW1hcnkoZGZfYmVmb3JlKQojc3Z5bWVhbih+IFdBR1AsZGZfYmVmb3JlLCBuYS5ybSA9IFQpCgpyYWRhcmRhdGEgPC0gZGF0YS5mcmFtZShncm91cCA9IGNoYXJhY3RlcigpLCB3YWdlID0gbnVtZXJpYygpLCBocl9wZXJfd2sgPSBudW1lcmljLCB3a19wZXJfeXIgPSBudW1lcmljKCksIGluY29tZV90b19wb3ZlcnR5ID0gbnVtZXJpYygpLCBkZWdyZWUgPSBudW1lcmljKCkpCnJhZGFyZGF0YSA8LSByYmluZChyYWRhcmRhdGEsIGRhdGEuZnJhbWUoZ3JvdXAgPSAiYmVmb3JlX3N0ZW0iLCB3YWdlID0gbWVhbihiZWZvcmVfc3RlbSRXQUdQKSwgaHJfcGVyX3drPW1lYW4oYmVmb3JlX3N0ZW0kV0tIUCksIHdrX3Blcl95cj1tZWFuKGJlZm9yZV9zdGVtJFdLVyksIGluY29tZV90b19wb3ZlcnR5PW1lYW4oYmVmb3JlX3N0ZW0kUE9WUElQLG5hLnJtPVRSVUUpLCBkZWdyZWU9bWVhbihiZWZvcmVfc3RlbSRTQ0hMKSkpCnJhZGFyZGF0YSA8LSByYmluZChyYWRhcmRhdGEsIGRhdGEuZnJhbWUoZ3JvdXAgPSAiYmVmb3JlX25vbnN0ZW0iLCB3YWdlID0gbWVhbihiZWZvcmVfbm9uc3RlbSRXQUdQKSwgaHJfcGVyX3drPW1lYW4oYmVmb3JlX25vbnN0ZW0kV0tIUCksIHdrX3Blcl95cj1tZWFuKGJlZm9yZV9ub25zdGVtJFdLVyksIGluY29tZV90b19wb3ZlcnR5PW1lYW4oYmVmb3JlX25vbnN0ZW0kUE9WUElQLG5hLnJtPVRSVUUpLCBkZWdyZWU9bWVhbihiZWZvcmVfbm9uc3RlbSRTQ0hMKSkpCnJhZGFyZGF0YSA8LSByYmluZChyYWRhcmRhdGEsIGRhdGEuZnJhbWUoZ3JvdXAgPSAiYWZ0ZXJfc3RlbSIsIHdhZ2UgPSBtZWFuKGFmdGVyX3N0ZW0kV0FHUCksIGhyX3Blcl93az1tZWFuKGFmdGVyX3N0ZW0kV0tIUCksIHdrX3Blcl95cj1tZWFuKGFmdGVyX3N0ZW0kV0tXKSwgaW5jb21lX3RvX3BvdmVydHk9bWVhbihhZnRlcl9zdGVtJFBPVlBJUCxuYS5ybT1UUlVFKSwgZGVncmVlPW1lYW4oYWZ0ZXJfc3RlbSRTQ0hMKSkpCnJhZGFyZGF0YSA8LSByYmluZChyYWRhcmRhdGEsIGRhdGEuZnJhbWUoZ3JvdXAgPSAiYWZ0ZXJfbm9uc3RlbSIsIHdhZ2UgPSBtZWFuKGFmdGVyX25vbnN0ZW0kV0FHUCksIGhyX3Blcl93az1tZWFuKGFmdGVyX25vbnN0ZW0kV0tIUCksIHdrX3Blcl95cj1tZWFuKGFmdGVyX25vbnN0ZW0kV0tXKSwgaW5jb21lX3RvX3BvdmVydHk9bWVhbihhZnRlcl9ub25zdGVtJFBPVlBJUCxuYS5ybT1UUlVFKSwgZGVncmVlPW1lYW4oYWZ0ZXJfbm9uc3RlbSRTQ0hMKSkpCnJhZGFyZGF0YSR3YWdlIDwtIHJhZGFyZGF0YSR3YWdlIC8gMTAwMApyYWRhcmRhdGEyIDwtIHJiaW5kKGMobWF4KHJhZGFyZGF0YSR3YWdlKSxtYXgocmFkYXJkYXRhJGhyX3Blcl93ayksbWF4KHJhZGFyZGF0YSR3a19wZXJfeXIpLG1heChyYWRhcmRhdGEkaW5jb21lX3RvX3BvdmVydHkpLG1heChyYWRhcmRhdGEkZGVncmVlKSksCiAgICAgICAgICAgICAgICAgICAgYyhtaW4ocmFkYXJkYXRhJHdhZ2UpLG1pbihyYWRhcmRhdGEkaHJfcGVyX3drKSxtaW4ocmFkYXJkYXRhJHdrX3Blcl95ciksbWluKHJhZGFyZGF0YSRpbmNvbWVfdG9fcG92ZXJ0eSksbWluKHJhZGFyZGF0YSRkZWdyZWUpKSwgCiAgICAgICAgICAgICAgICAgICAgcmFkYXJkYXRhWyxjKDI6NildKQoKY29sb3JzX2JvcmRlcj1jKHJnYigwLjIsMC41LDAuNSwwLjkpLCByZ2IoMC44LDAuMiwwLjUsMC45KSAsIHJnYigwLjcsMC41LDAuMSwwLjkpLCByZ2IoMC41LDAuMiwwLjEsMC45KSApCmNvbG9yc19pbj1jKCByZ2IoMC4yLDAuNSwwLjUsMC40KSwgcmdiKDAuOCwwLjIsMC41LDAuNCkgLCByZ2IoMC43LDAuNSwwLjEsMC40KSwgcmdiKDAuNSwwLjIsMC4xLDAuNCkgKQpyYWRhcmNoYXJ0KHJhZGFyZGF0YTIgLCBheGlzdHlwZT0xICwgCiAgICAgICAgICAgIyBjdXN0b20gcG9seWdvbgogICAgICAgICAgIHBjb2w9Y29sb3JzX2JvcmRlciAsIHBmY29sPWNvbG9yc19pbiAsIHBsd2Q9MyAsIHBsdHk9MSwKICAgICAgICAgICAjIGN1c3RvbSB0aGUgZ3JpZAogICAgICAgICAgIGNnbGNvbD0iZ3JleSIsIGNnbHR5PTIsIGF4aXNsYWJjb2w9ImdyZXkiLCAKICAgICAgICAgICBjYXhpc2xhYmVscyA9IGMoJ01pbiAgICAgICAgICAgICcsJycsJycsJycsJ01heCAgICAgICAgICcpLAogICAgICAgICAgIGNnbHdkPTAuNQopCmxlZ2VuZCh4PTAuOSwgeT0xLjQsIGxlZ2VuZCA9IHJhZGFyZGF0YVssMV0sIGJ0eSA9ICJuIiwgcGNoPTIwICwgY29sPWNvbG9yc19ib3JkZXIgLCBjZXg9MC45LCBwdC5jZXg9MSkKdGl0bGUoIkNoYW5nZXMgaW4gV29ya2luZyBDb25kaXRpb25zIEFmdGVyIFNURU0gUG9saWN5IFdlbnQgT3V0ICIsIGNleC5tYWluPTEpCmBgYAoKIyMjIyAoMykgQ2xhc3MvR2VuZGVyIFN0cnVjdHVyZSBvZiBTVEVNIEpvYnMKCgpOb3cgbGV0J3Mgc3R1ZHkgdGhlIGNsYXNzIG9mIHdvcmsgc3RydWN0dXJlIGFuZCBnZW5kZXIgc3RydWN0dXJlIGluIFNURU0vbm9uLVNURU0gam9icy4KCldoaWxlIHRoZSBjbGFzcyBvZiB3b3JrIHN0cnVjdHVyZSBvZiBub24tU1RFTSBqb2JzIHJlbWFpbnMgYWxtb3N0IHRoZSBzYW1lIGFmdGVyIFNURU0gcG9saWN5IHdlbnQgb3V0LCB3ZSBjb3VsZCB0ZWxsIHRoZSBjaGFuZ2Ugb2YgU1RFTSBqb2JzIHN0cnVjdHVyZSBpbiB0aGUgcGFzdCBkZWNhZGUuIENvbXBhcmVkIHRvIG5vbi1TVEVNIGdyb3VwLCBsZXNzIFNURU0gam9icyBhcmUgb2Ygc2VsZi1lbXBsb3llZCBvciBmb3Igbm90LWZvci1wcm9maXQgb3JnYW5pemF0aW9ucy4gSW5zdGVhZCwgU1RFTSBwZW9wbGUgdGVuZCB0byBzdGF5IGF0IGZvci1wcm9maXQgY29tcGFuaWVzLiBUaGlzIGNoYW5nZSBjb3VsZCBiZSByZWxldmFudCB0byBib3RoIHRoZSBjaGFuZ2Ugb2YgdGhlIFNURU0gaW5kdXN0cmllcyBhbmQgdGhlIHRob3VnaHQgY29udmVyc2lvbiBvZiBTVEVNIHBlb3BsZS4gSXQncyBsaWtlbHkgdGhhdCBmb3IgdGhlc2UgcGVvcGxlLCBmb3ItcHJvZml0IGNvbXBhbnkgaXMgdGhlIG9wdGlvbiB3aGljaCBhbGxvd3MgYmV0dGVyIHNlbGYtZnVsZmlsbG1lbnQuCmBgYHtyfQojIDMgY293LCBzZXgKY293IDwtIGRhdGEuZnJhbWUodGFibGUoYmVmb3JlX3N0ZW0kQ09XKSkKY293IDwtIGNiaW5kKGNvdyx0YWJsZShiZWZvcmVfbm9uc3RlbSRDT1cpKQpjb3cgPC0gY2JpbmQoY293LHRhYmxlKGFmdGVyX3N0ZW0kQ09XKSkKY293IDwtIGNiaW5kKGNvdyx0YWJsZShhZnRlcl9ub25zdGVtJENPVykpCmNvdyA8LSBjb3dbLGMoMSwyLDQsNiw4KV0KbmFtZXMoY293KSA8LSBjKCdDbGFzcycsICdiZWZvcmVfc3RlbScsICAnYmVmb3JlX25vbnN0ZW0nLCdhZnRlcl9zdGVtJywnYWZ0ZXJfbm9uc3RlbScpCmNvd1ssMl0gPSBjb3dbLDJdL3N1bShjb3dbLDJdKQpjb3dbLDNdID0gY293WywzXS9zdW0oY293WywzXSkKY293Wyw0XSA9IGNvd1ssNF0vc3VtKGNvd1ssNF0pCmNvd1ssNV0gPSBjb3dbLDVdL3N1bShjb3dbLDVdKQoKc2V4IDwtIGRhdGEuZnJhbWUodGFibGUoYmVmb3JlX3N0ZW0kU0VYKSkKc2V4IDwtIGNiaW5kKHNleCx0YWJsZShiZWZvcmVfbm9uc3RlbSRTRVgpKQpzZXggPC0gY2JpbmQoc2V4LHRhYmxlKGFmdGVyX3N0ZW0kU0VYKSkKc2V4IDwtIGNiaW5kKHNleCx0YWJsZShhZnRlcl9ub25zdGVtJFNFWCkpCnNleCA8LSBzZXhbLGMoMSwyLDQsNiw4KV0KbmFtZXMoc2V4KSA8LSBjKCdTZXgnLCAnYmVmb3JlX3N0ZW0nLCAgJ2JlZm9yZV9ub25zdGVtJywnYWZ0ZXJfc3RlbScsJ2FmdGVyX25vbnN0ZW0nKQpzZXhbLDJdID0gc2V4WywyXS9zdW0oc2V4WywyXSkKc2V4WywzXSA9IHNleFssM10vc3VtKHNleFssM10pCnNleFssNF0gPSBzZXhbLDRdL3N1bShzZXhbLDRdKQpzZXhbLDVdID0gc2V4Wyw1XS9zdW0oc2V4Wyw1XSkKCmNvd19tZWx0ID0gbWVsdChjb3csIGlkLnZhcnMgPSBjKCdDbGFzcycpKQpnZ3Bsb3QoY293X21lbHQsYWVzKHggPSB2YXJpYWJsZSwgeSA9IHZhbHVlLGZpbGwgPSBDbGFzcykpICsgCiAgZ2VvbV9iYXIocG9zaXRpb24gPSAiZmlsbCIsc3RhdCA9ICJpZGVudGl0eSIpICsgCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkgKwogIGdndGl0bGUoIkNoYW5nZXMgaW4gQ2xhc3Mgb2YgV29yayBBZnRlciBTVEVNIFBvbGljeSBXZW50IE91dCIpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSByZWwoMSksZmFjZT0iYm9sZCIpKSArCiAgeGxhYigiIikgKwogIHlsYWIoIkNvbXBvbmVudCBQcm9wb3J0aW9uIikKYGBgCgpJZiB3ZSB0cnkgdG8gYWRkcmVzcyB0aGUgZ2VuZGVyIHByb3BvcnRpb24gaW4gam9icywgd2UgZ2V0IHNvbWUgbW9yZSBpbnRlcmVzdGluZyBmaW5kaW5ncy4gRmlyc3Qgb2YgYWxsLCB0aGUgZ2VuZGVyIGVxdWFsaXR5IHNlZW1zIHRvIGJlIHF1aXRlIHRlbmFibGUgaW4gbm9uLVNURU0gam9icy4gSG93ZXZlciwgd2hlbiBzcGVha2luZyBvZiBTVEVNIGpvYnMsIHRoZSBwZXJjZW50YWdlIG9mIGZlbWFsZSBlbXBsb3llZXMgZHJvcHBlZCBzaWduaWZpY2FudGx5IGFmdGVyIFNURU0gcG9saWN5IHdlbnQgb3V0LiBXaGF0IGNvdWxkIGJlIHRoZSBwb3RlbnRpYWwgcmVhc29ucz8gSWYgaXQgaXMgcmVsZXZhbnQgdG8gU1RFTSBwb2xpY3ksIGRvZXMgdGhpcyBtZWFuIHRoYXQgU1RFTSBwb2xpY3kgaXMgbW9yZSBhcHBlYWxpbmcgdG8gbWFsZSBmb3JlaWduIHN0dWRlbnRzIGNvbXBhcmVkIHRvIGZlbWFsZSwgYW5kIHRoZXJlZm9yZSBtb3JlIG1hbGVzIGNvbWUgdG8gVVMgYW5kIHN0YXk/IApZZXQsIGlmIHdlIGNvbnNpZGVyIHRoZSBmYWN0IHRoYXQgdGhlIHByb3BvcnRpb24gb2Ygbm9uLVVTLWJvcm4gZW1wbG95ZWVzIGluIHRoZSBTVEVNIGpvYnMgaXMgYWN0dWFsbHkgbm90IHRoYXQgYmlnLCB3ZSBzaG91bGQgcmVhbGl6ZSB0aGF0IFNURU0gcG9saWN5IGNvdWxkIG5vdCBiZSB0aGUgbWFqb3IgY2F1c2UuIEluIG90aGVyIHdvcmRzLCB0aGVyZSdyZSBzb21lIG90aGVyIGZhY3RvcnMgdGhhdCBhcmUgY3VycmVudGx5IGluZmx1ZW5jaW5nIHRoZSBnZW5kZXIgc3RydWN0dXJlIGluIFNURU0gam9icywgYW5kIHdlIHNob3VsZCBwYXkgYXR0ZW50aW9uIHRvIHRoaXMgaHVnZSBnZW5kZXIgZ2FwLgpgYGB7cn0KY29sb3JzX2luMT1jKCdyb3N5YnJvd24xJywgJ2xpZ2h0c3RlZWxibHVlMicpCmNvbG9yc19pbjI9Yygncm9zeWJyb3duMycsICdsaWdodHN0ZWVsYmx1ZTQnKQpjb2xvcnNfaW4zPWMoJ3RhbjEnLCdzZWFncmVlbjEnKQpjb2xvcnNfaW40PWMoJ3RhbjMnLCdzZWFncmVlbjMnKQpjb2xvcnNfaW49Yygncm9zeWJyb3duMScsICdsaWdodHN0ZWVsYmx1ZTInLCdyb3N5YnJvd24zJywgJ2xpZ2h0c3RlZWxibHVlNCcpCnBpZSh4PWMoc2V4WzEsMl0sc2V4WzIsMl0pLGxhYmVscz1jKCIiKSxjZXg9MSxyYWRpdXM9MSxjb2w9Y29sb3JzX2luMSkKcGFyKG5ldz1UUlVFKQpwaWUoeD1jKHNleFsxLDNdLHNleFsyLDNdKSxsYWJlbHM9YygiIiksIGNleD0wLjgscmFkaXVzPTAuNzUsY29sPWNvbG9yc19pbjIpCnBhcihuZXc9VFJVRSkKcGllKHg9YyhzZXhbMSw0XSxzZXhbMiw0XSksbGFiZWxzPWMoIiIpLGNleD0xLHJhZGl1cz0wLjUsY29sPWNvbG9yc19pbjMpCnBhcihuZXc9VFJVRSkKcGllKHg9YyhzZXhbMSw1XSxzZXhbMiw1XSksbGFiZWxzPWMoIiIpLGNleD0wLjgscmFkaXVzPTAuMjUsY29sPWNvbG9yc19pbjQpCmxlZ2VuZCh4PTEuNSwgeT0wLjUsIGxlZ2VuZCA9IGMoJycsJycpLCBjb2wgPSBjb2xvcnNfaW4xLCBidHkgPSAibiIsIHBjaD0yMCAsY2V4PTAuOCwgcHQuY2V4PTIpCmxlZ2VuZCh4PTEuOSwgeT0wLjUsIGxlZ2VuZCA9IGMoJycsJycpLCBjb2wgPSBjb2xvcnNfaW4zLCBidHkgPSAibiIsIHBjaD0yMCAsY2V4PTAuOCwgcHQuY2V4PTIpCnRleHQoJzIwMDcnLCB4PTEuNiwgeT0wLjYsY2V4PTAuOCkKdGV4dCgnMjAxNCcsIHg9MiwgeT0wLjYsY2V4PTAuOCkKdGV4dCgnZmVtYWxlJywgeD0xLjIsIHk9MC40LGNleD0wLjgpCnRleHQoJ21hbGUnLCB4PTEuMiwgeT0wLjI1LGNleD0wLjgpCmxlZ2VuZCh4PTEuNSx5PTAuLGxlZ2VuZD1jKCcnLCcnKSxjb2w9Yygnd2hpdGUnLCdncmV5JyksYnR5ID0gIm4iLCAgcGNoPTIwICxjZXg9MC44LCBwdC5jZXg9MikKbGVnZW5kKHg9MS40NzUseT0wLjA1LHB0LmNleD0xLjQsIGJ0eSA9ICJuIiwgbGVnZW5kID0gYygiIiksIHBjaCA9IDIxKQp0ZXh0KCdzdGVtJywgeD0xLjIsIHk9LTAuMTEsY2V4PTAuOCkKdGV4dCgnbm9uLXN0ZW0nLCB4PTEuMjUsIHk9LTAuMjUsY2V4PTAuOCkKdGl0bGUoIkNoYW5nZXMgaW4gR2VuZGVyIFByb3BvcnRpb24gb2YgSm9icyBBZnRlciBTVEVNIFBvbGljeSBXZW50IE91dCIsY2V4PTAuOCkKYGBgCgojIyMjICg0KSBJbW1pZ3JhdGlvbiBCZWhhdmlvcnMKCklmIHdlIGFzc3VtZSB0aGUgU1RFTSBwb2xpY3kgZG9lcyBhdHRyYWN0IGEgbG90IG9mIGZvcmVpZ24gc3R1ZGVudHMgdG8gY29tZSBhbmQgc3R1ZHkgaW4gVVMsIGRvZXMgaXQgbWVhbiB0aGF0IHRoaXMgcG9saWN5IHdpbGwgZnVydGhlciBpbmZsdWVuY2UgdGhlbSB0byBzdGF5IGluIFVTIHBlcm1hbmVudGx5PwpUbyBhbnN3ZXIgdGhpcyBxdWVzdGlvbiwgd2UgZHJhdyB0aGUgZm9sbG93aW5nIGZpZ3VyZSBhbmQgd2Uga25vdyB0aGUgYW5zd2VyIGlzIE5PLiBUaGUgZmlndXJlIGdlbmVyYWxseSBwcmVzZW50cyB0aGUgZGlzdHJpYnV0aW9uIG9mIGFnZSBvZiBlbnRyeSBhbW9uZyBpbW1pZ3JhbnRzIHRvIFVTLiBXZSBjYW4gc2VlIGZyb20gdGhlIHBsb3QgdGhhdCB0aGUgcHJvcG9ydGlvbiBvZiBpbW1pZ3JhbnRzIHdobyBjYW1lIHRvIFVTIGR1cmluZyB0aGVpciBhZ2Ugb2Ygc2Nob29saW5nIGRpZG4ndCBjaGFuZ2UgbXVjaCBhcyB0aGUgU1RFTSBwb2xpY3kgYmVpbmcgcHVibGlzaGVkLCBlaXRoZXIgZm9yIFNURU0gb3Igbm9uLVNURU0gcGVvcGxlLgpgYGB7cn0KIyA0IHllYXIgb2YgZW50cnktc3RlbS9ub25zdGVtLWJlZm9yZS9hZnRlciAoZm9yIHRob3NlIHdobyBuYXR1cmFsaXplZCkKYmVmb3JlX25hdHVyYWxpemUgPC0gYmVmb3JlX2RhdGFbYmVmb3JlX2RhdGEkQ0lUID09IDRdCmFmdGVyX25hdHVyYWxpemUgPC0gYWZ0ZXJfZGF0YVthZnRlcl9kYXRhJENJVCA9PSA0XQpiZWZvcmVfbmF0dXJhbGl6ZSRBR0VPRkVOVFJZIDwtIGJlZm9yZV9uYXR1cmFsaXplJFlPRVAgLSAoMjAwNyAtIGJlZm9yZV9uYXR1cmFsaXplJEFHRVApCmFmdGVyX25hdHVyYWxpemUkQUdFT0ZFTlRSWSA8LSBhZnRlcl9uYXR1cmFsaXplJFlPRVAgLSAoMjAxNCAtIGFmdGVyX25hdHVyYWxpemUkQUdFUCkKCmJlZm9yZV9uYXR1cmFsaXplX3N0ZW0gPC0gYmVmb3JlX25hdHVyYWxpemVbYmVmb3JlX25hdHVyYWxpemUkU09DUCA9PSAnU1RFTSddCmJlZm9yZV9uYXR1cmFsaXplX25vbnN0ZW0gPC0gYmVmb3JlX25hdHVyYWxpemVbYmVmb3JlX25hdHVyYWxpemUkU09DUCA9PSAnTk9OLVNURU0nXQphZnRlcl9uYXR1cmFsaXplX3N0ZW0gPC0gYWZ0ZXJfbmF0dXJhbGl6ZVthZnRlcl9uYXR1cmFsaXplJFNPQ1AgPT0gJ1NURU0nXQphZnRlcl9uYXR1cmFsaXplX25vbnN0ZW0gPC0gYWZ0ZXJfbmF0dXJhbGl6ZVthZnRlcl9uYXR1cmFsaXplJFNPQ1AgPT0gJ05PTi1TVEVNJ10KCmJlZm9yZV9uYXR1cmFsaXplX2FnZV9zdGVtIDwtIGN1dChiZWZvcmVfbmF0dXJhbGl6ZV9zdGVtJEFHRU9GRU5UUlksIHNlcSgwLDEwMCxsZW5ndGgub3V0PTIxKSkKYmVmb3JlX25hdHVyYWxpemVfYWdlX3N0ZW0gPC0gZGF0YS5mcmFtZSh0YWJsZShiZWZvcmVfbmF0dXJhbGl6ZV9hZ2Vfc3RlbSkpCmJlZm9yZV9uYXR1cmFsaXplX2FnZV9ub25zdGVtIDwtIGN1dChiZWZvcmVfbmF0dXJhbGl6ZV9ub25zdGVtJEFHRU9GRU5UUlksIHNlcSgwLDEwMCxsZW5ndGgub3V0PTIxKSkKYmVmb3JlX25hdHVyYWxpemVfYWdlX25vbnN0ZW0gPC0gZGF0YS5mcmFtZSh0YWJsZShiZWZvcmVfbmF0dXJhbGl6ZV9hZ2Vfbm9uc3RlbSkpCmFmdGVyX25hdHVyYWxpemVfYWdlX3N0ZW0gPC0gY3V0KGFmdGVyX25hdHVyYWxpemVfc3RlbSRBR0VPRkVOVFJZLCBzZXEoMCwxMDAsbGVuZ3RoLm91dD0yMSkpCmFmdGVyX25hdHVyYWxpemVfYWdlX3N0ZW0gPC0gZGF0YS5mcmFtZSh0YWJsZShhZnRlcl9uYXR1cmFsaXplX2FnZV9zdGVtKSkKYWZ0ZXJfbmF0dXJhbGl6ZV9hZ2Vfbm9uc3RlbSA8LSBjdXQoYWZ0ZXJfbmF0dXJhbGl6ZV9ub25zdGVtJEFHRU9GRU5UUlksIHNlcSgwLDEwMCxsZW5ndGgub3V0PTIxKSkKYWZ0ZXJfbmF0dXJhbGl6ZV9hZ2Vfbm9uc3RlbSA8LSBkYXRhLmZyYW1lKHRhYmxlKGFmdGVyX25hdHVyYWxpemVfYWdlX25vbnN0ZW0pKQoKbmF0dXJhbGl6ZWRfYWdlX3N0ZW0gPC0gbWVyZ2UoYmVmb3JlX25hdHVyYWxpemVfYWdlX3N0ZW0sYWZ0ZXJfbmF0dXJhbGl6ZV9hZ2Vfc3RlbSwgYnkueD0iYmVmb3JlX25hdHVyYWxpemVfYWdlX3N0ZW0iLCBieS55PSdhZnRlcl9uYXR1cmFsaXplX2FnZV9zdGVtJykKbmFtZXMobmF0dXJhbGl6ZWRfYWdlX3N0ZW0pIDwtIGMoJ2FnZV9yYW5nZScsJ2JlZm9yZV9zdGVtJywnYWZ0ZXJfc3RlbScpCm5hdHVyYWxpemVkX2FnZV9zdGVtJGJlZm9yZV9zdGVtID0gbmF0dXJhbGl6ZWRfYWdlX3N0ZW0kYmVmb3JlX3N0ZW0vc3VtKG5hdHVyYWxpemVkX2FnZV9zdGVtJGJlZm9yZV9zdGVtKQpuYXR1cmFsaXplZF9hZ2Vfc3RlbSRhZnRlcl9zdGVtID0gbmF0dXJhbGl6ZWRfYWdlX3N0ZW0kYWZ0ZXJfc3RlbS9zdW0obmF0dXJhbGl6ZWRfYWdlX3N0ZW0kYWZ0ZXJfc3RlbSkKbmF0dXJhbGl6ZWRfYWdlX25vbnN0ZW0gPC0gbWVyZ2UoYmVmb3JlX25hdHVyYWxpemVfYWdlX25vbnN0ZW0sYWZ0ZXJfbmF0dXJhbGl6ZV9hZ2Vfbm9uc3RlbSwgYnkueD0iYmVmb3JlX25hdHVyYWxpemVfYWdlX25vbnN0ZW0iLCBieS55PSdhZnRlcl9uYXR1cmFsaXplX2FnZV9ub25zdGVtJykKbmFtZXMobmF0dXJhbGl6ZWRfYWdlX25vbnN0ZW0pIDwtIGMoJ2FnZV9yYW5nZScsJ2JlZm9yZV9ub25zdGVtJywnYWZ0ZXJfbm9uc3RlbScpCm5hdHVyYWxpemVkX2FnZV9ub25zdGVtJGJlZm9yZV9ub25zdGVtID0gbmF0dXJhbGl6ZWRfYWdlX25vbnN0ZW0kYmVmb3JlX25vbnN0ZW0vc3VtKG5hdHVyYWxpemVkX2FnZV9ub25zdGVtJGJlZm9yZV9ub25zdGVtKQpuYXR1cmFsaXplZF9hZ2Vfbm9uc3RlbSRhZnRlcl9ub25zdGVtID0gbmF0dXJhbGl6ZWRfYWdlX25vbnN0ZW0kYWZ0ZXJfbm9uc3RlbS9zdW0obmF0dXJhbGl6ZWRfYWdlX25vbnN0ZW0kYWZ0ZXJfbm9uc3RlbSkKCm5hdHVyYWxpemVkX2FnZSA8LSBjYmluZChuYXR1cmFsaXplZF9hZ2Vfc3RlbSxuYXR1cmFsaXplZF9hZ2Vfbm9uc3RlbSkKbmF0dXJhbGl6ZWRfYWdlIDwtIG5hdHVyYWxpemVkX2FnZVssYygxLDIsNSwzLDYpXQpuYXR1cmFsaXplZF9hZ2UgPC0gbWVsdChuYXR1cmFsaXplZF9hZ2UsIGlkPSdhZ2VfcmFuZ2UnKQpnZ3Bsb3QoZGF0YT1uYXR1cmFsaXplZF9hZ2UsCiAgICAgICBhZXMoeD1hZ2VfcmFuZ2UsIHk9dmFsdWUsIGNvbD12YXJpYWJsZSwgZ3JvdXA9dmFyaWFibGUpKSArCiAgICAgICBnZW9tX2xpbmUoKSsKICAgICAgIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpICsKICAgICAgIGdndGl0bGUoIkNoYW5nZXMgaW4gQWdlIG9mIEVudHJ5IEFtb25nIEltbWlncmFudHMiKSArCiAgICAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSByZWwoMSksZmFjZT0iYm9sZCIpKSArCiAgICAgICB5bGFiKCJQcm9wb3J0aW9uIikKYGBgCgojIyBTdW1tYXJ5CgpXZSBrbm93IG1vcmUgYWJvdXQgU1RFTSBhZnRlciB0aGlzIHByb2plY3QuIFdlIGxlYXJuIGhvdyBTVEVNIGRlZ3JlZXMgcmVsYXRlIHRvIGRpZmZlcmVudCBpbmR1c3RyaWVzIGFuZCB3ZSBoYXZlIGEgYmFzaWMgdW5kZXJzdGFuZGluZyB3aGF0IG91ciBqb2Igd2lsbCBiZSBsaWtlLgoKQXMgZ3JhZHVhdGluZyBTVEVNIGRlZ3JlZSBzdHVkZW50cyBpbiBOWSwgb3VyIGNhcmVlciBmdXR1cmUgaXMgcHJvbWlzaW5nLiBJbiBzcGl0ZSBvZiBOWSBhbmQgQ0EsIHNvbWUgb3RoZXIgc3RhdGVzIGluY2x1ZGluZyBUZXhhcyBhbmQgVmlyZ2luaWEgYWxzbyBwcm92aWRlIGEgZ29vZCBhbW91bnQgb2Ygam9iIG9wZW5pbmcuIENvbnNpZGVyaW5nIHdvcmtpbmcgY29uZGl0aW9ucyBvbmx5LCBpdCdzIGEgZmFpciBjaG9pY2UgZm9yIHVzIHRvIGZ1cnRoZXIgcHVyc3VlIGEgUGhEIGRlZ3JlZS4KCkhvd2V2ZXIsIHRoZSBjdXJyZW50IGdlbmRlciBkaXNwYXJpdHkgaW4gU1RFTSBqb2JzIGlzIGEgcXVlc3Rpb24gd29ydGggdGhpbmtpbmcgYWJvdXQuIFRoZSBmZW1hbGUgcHJvcG9ydGlvbiBkcm9wcGVkIGZyb20gNDclIHRvIDI1JSBhbmQgdGhpcyBpcyBub24tbmVnbGlnaWJsZS4gCgpBYm92ZSBpcyB0aGUgcHJvamVjdCBvZiBvdXIgdGVhbS4gVGhhbmsgeW91IGFsbCBmb3IgbGlzdGVuaW5nIQ==